英文:
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个图像之外,所有添加的图像都被替换为最后添加的图像。
英文:
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 "./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 code to update the state of the array of images
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
},
]
const newtestimagesobject = {
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>
</>
)
}
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.
答案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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论