useState为何无法正常工作并显示最后更新的内容

huangapple go评论68阅读模式
英文:

Why useState is not working properly and showing last updated content

问题

我正在使用React的useState()创建一个测试应用程序,当我使用一个表单获取图像名称和URL,然后从该输入创建一个新对象,并将该对象添加到setImages()函数中时,它会用最后添加的图像替换所有新添加的图像。我正在分享我用于获取用户输入的HTML表单和用于获取新图像对象的函数以及用于更新状态以便将其添加到所有图像数组中的代码。

React代码用于获取用户输入并创建一个传递给添加到图像数组中的函数的对象:

import "./addImageButton.css";
import { ThemeContext } from "./mycontents";
import { useContext, useEffect, useRef } from "react";

let formInput = {
    id: Math.floor(Math.random() * 100000),
    like: true
};

export function AddImageButton({ addANewImages }) {
    console.log("Add image button");
    const themecontext = useContext(ThemeContext);
    console.log(themecontext);
    const addImageNameValue = useRef("null");

    useEffect(() => {
        addImageNameValue.current.value = "Image Name";
        console.log("inside userref 1");
    });

    console.log("HI");

    function handleInputChange(e) {
        console.log(e.target.imageName);
        if (e.target.name === "imageName") {
            formInput["imageContent"] = e.target.value;
        }

        if (e.target.name === "imageLink") {
            formInput["imageUrl"] = e.target.value;
        }
    }

    function handleSubmit(e) {
        e.preventDefault();
        addANewImages(formInput);
    }

    return (
        <>
            <div style={{ marginTop: "5px" }}>
                <form>
                    <input
                        placeholder="Enter Image Name"
                        name="imageName"
                        ref={addImageNameValue}
                        type="text"
                        onChange={handleInputChange}
                        autoFocus
                    ></input>
                    <input
                        placeholder="Enter Image Link"
                        name="imageLink"
                        type="text"
                        onChange={handleInputChange}
                    ></input>
                    <button type="submit" onClick={handleSubmit}>
                        Add New Image
                    </button>
                </form>
            </div>
        </>
    );
}

React代码用于更新图像数组的状态:

import { useState } from "react";
import "./index.css";
import { AddImageButton } from "./addImageButton";
import { DeleteImage } from "./deletedImageButton.js";
import { useContext } from "react";
import { ThemeContext } from "./mycontents";
import { MyCounter } from "./mycounter";

const initialImages = [
    {
        id: 0,
        imageUrl: "https://cdn.pixabay.com/photo/2023/05/23/23/58/moth-8013720_640.jpg",
        imageContent: "Butterfly",
        like: true
    },
    {
        id: 1,
        imageUrl: "https://cdn.pixabay.com/photo/2023/06/11/19/09/fruit-8056663_1280.jpg",
        imageContent: "Pineapple",
        like: true
    },
];

export function MyImageCard() {
    const [images, setImages] = useState(initialImages);

    function addANewImages(newImage) {
        setImages((images) => [...images, newImage]);
    }

    function deletingImageID(imageID) {
        const imagesAfterDelete = images.filter((value) => {
            if (value.id !== Number(imageID) || imageID === null) {
                return value;
            }
        });

        console.log(imagesAfterDelete);
        setImages([...imagesAfterDelete]);
    }

    console.log("App");
    const themecontext = useContext(ThemeContext);
    console.log(themecontext);

    return (
        <>
            {images.map((value) => {
                return (
                    <>
                        <div className="imageContainer">
                            <img src={value.imageUrl} alt={value.imageContent}></img>
                            <br />
                            <span>
                                {value.id}. {value.imageContent} {value.like ? "✨" : ""}
                            </span>
                        </div>
                    </>
                );
            })}
            <ThemeContext.Provider value="Vivek">
                <AddImageButton addANewImages={addANewImages}></AddImageButton>
            </ThemeContext.Provider>
            <DeleteImage deletingImageID={deletingImageID}></DeleteImage>
            <MyCounter></MyCounter>
        </>
    );
}

结果显示React代码,如您所见,除了硬编码的前5个图像之外,所有添加的图像都被替换为最后添加的图像。

useState为何无法正常工作并显示最后更新的内容

英文:

I am creating a test application using react useState() and when i getting the image name and url using a form and then create a new object from that input and adding that object to the setImages() function then it is replace all the newly added images with the image that was added at the last. I am sharing the code that i am using to get the user input using HTML form and the function to get the new image object and code to update the state so that it can be added to array of all the images.

React code to get the use input and creating a object which is passed in the function which will add it to the array of images


import &quot;./addImageButton.css&quot;
import { ThemeContext } from &quot;./mycontents&quot;
import { useContext, useEffect, useRef } from &quot;react&quot;;
let formInput = {
id: Math.floor(Math.random() * 100000),
like: true
}
export function AddImageButton({ addANewImages }) {
console.log(&quot;Add image button&quot;)
const themecontext = useContext(ThemeContext)
console.log(themecontext)
const addImageNameValue = useRef(&quot;null&quot;)
useEffect(()=&gt;{
addImageNameValue.current.value = &quot;Image Name&quot;
console.log(&quot;inside userref 1&quot;);
})
console.log(&quot;HI&quot;);
function handleInputChange(e) {
console.log(e.target.imageName);
if (e.target.name === &quot;imageName&quot;) {
formInput[&quot;imageContent&quot;] = e.target.value
}
if (e.target.name === &quot;imageLink&quot;) {
formInput[&quot;imageUrl&quot;] = e.target.value
}
}
function handleSubmit(e) {
e.preventDefault()
addANewImages(formInput)
}
return (
&lt;&gt;
&lt;div style={{ marginTop: &quot;5px&quot; }}&gt;
&lt;form&gt;
&lt;input placeholder=&quot;Enter Image Name&quot;  name=&quot;imageName&quot; ref={addImageNameValue} type=&quot;text&quot; onChange={handleInputChange} autoFocus&gt;&lt;/input&gt;
&lt;input placeholder=&quot;Enter Image Link&quot; name=&quot;imageLink&quot; type=&quot;text&quot; onChange={handleInputChange}&gt;&lt;/input&gt;
&lt;button type=&quot;submit&quot; onClick={handleSubmit}&gt;
Add New Image
&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/&gt;
)
}

React code to update the state of the array of images


import { useState } from &quot;react&quot;
import &quot;./index.css&quot;
import { AddImageButton } from &quot;./addImageButton&quot;
import { DeleteImage } from &quot;./deletedImageButton.js&quot;
import { useContext } from &quot;react&quot;
import { ThemeContext } from &quot;./mycontents&quot;
import { MyCounter } from &quot;./mycounter&quot;
const initialImages = [
{
id: 0,
imageUrl: &quot;https://cdn.pixabay.com/photo/2023/05/23/23/58/moth-8013720_640.jpg&quot;,
imageContent: &quot;Butterfly&quot;,
like: true
},
{
id: 1,
imageUrl: &quot;https://cdn.pixabay.com/photo/2023/06/11/19/09/fruit-8056663_1280.jpg&quot;,
imageContent: &quot;Pineapple&quot;,
like: true
},
]
const newtestimagesobject =    {
imageUrl: &quot;https://cdn.pixabay.com/photo/2023/06/11/19/09/fruit-8056663_1280.jpg&quot;,
imageContent: &quot;Pineapple&quot;,
like: true
}
export function MyImageCard() {
const [images, setImages] = useState(initialImages)
function addANewImages(newImage){
setImages(images=&gt;[...images,newImage])
}
function deletingImageID(imageID) {
const imagesAfterDelete = images.filter((value) =&gt; {
if (value.id !== Number(imageID) || imageID === null) {
return value
}
})
console.log(imagesAfterDelete);
setImages([...imagesAfterDelete]);
}
console.log(&quot;App&quot;)
const themecontext = useContext(ThemeContext)
console.log(themecontext)
return (
&lt;&gt;
{
images.map((value) =&gt; {
return (
&lt;&gt;
&lt;div className=&quot;imageContainer&quot;&gt;
&lt;img src={value.imageUrl} alt={value.imageContent}&gt;&lt;/img&gt;
&lt;br /&gt;
&lt;span&gt;{value.id}. {value.imageContent} {value.like ? &quot;✨&quot; : &quot;&quot;}&lt;/span&gt;
&lt;/div&gt;
&lt;/&gt;
)
})
}
&lt;ThemeContext.Provider value=&quot;Vivek&quot;&gt;
&lt;AddImageButton addANewImages={addANewImages}&gt;&lt;/AddImageButton&gt;
&lt;/ThemeContext.Provider&gt;
&lt;DeleteImage deletingImageID={deletingImageID}&gt;&lt;/DeleteImage&gt;
&lt;MyCounter&gt;&lt;/MyCounter&gt;
&lt;/&gt;
)
}

Result of the react code as you can see the all the images added are replaced with the images added art the last except the first 5 images which are hard coded.

useState为何无法正常工作并显示最后更新的内容

答案1

得分: 0

问题与您管理formInput对象的方式有关。目前,您在组件外部声明了formInput,这意味着它在渲染之间保留其值,因此当您添加新图像时,状态中的所有先前图像都会更新为最后添加的图像,因为它们引用了相同的formInput对象

您应该将formInput移到handleSubmit函数内部,以便每次提交表单时都创建一个新对象

function handleSubmit(e) {
  e.preventDefault();

  const formInput = {
    id: Math.floor(Math.random() * 100000),
    imageContent: addImageNameValue.current.value,
    imageUrl: e.target.imageLink.value,
    like: true,
  };

  addANewImages(formInput);
}
英文:

The issue is related to the way you're managing the formInput object. Currently, you're declaring formInput outside of your component, which means it keeps its value between renders, so when you add a new image, all previous images in the state are updated with the last added image because they reference the same formInput object.

you should move the formInput inside the handleSubmit function, so that a new object is created each time the form is submitted.

  function handleSubmit(e) {
    e.preventDefault();

    const formInput = {
      id: Math.floor(Math.random() * 100000),
      imageContent: addImageNameValue.current.value,
      imageUrl: e.target.imageLink.value,
      like: true,
    };

    addANewImages(formInput);
  }

huangapple
  • 本文由 发表于 2023年7月3日 14:26:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76602289.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定