状态更新不影响视图
state update not affecting on view
我正在做一个基本的 React 项目,我在其中对对象和数组进行反应状态,我想在这里完成的是我想将对象推送到 images
数组,我想在组件中呈现它,到目前为止,我用谷歌搜索了一些东西,我发现很少有方法可以完成它 array.concat
和 array.push
,我尝试了这两种方法它正在更新状态但它不影响组件
下面是我试过的代码
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
var obj = { src: "", imgdata: "" };
proClrData[key].images = proClrData[key].images.concat(obj);
console.log(proClrData);
};
下面是组件代码
{proClrData.length >= 1 &&
proClrData?.map((clr, key) => {
return (
<div key={key}>
<p className="pt-3 ">{clr.color}</p>
<div className="form-group">
<input
label="Price"
name="price"
value={clr?.price}
type="number"
fullWidth
required
/>
</div>
<div className="form-group pt-3">
<input
label="Quantity"
name="qty"
value={clr?.qty}
type="number"
fullWidth
required
/>
</div>
<div className="text-end pt-3">
<button
variant="contained"
color="primary"
onClick={() => addImages(key)}
>
Add Images
</button>
</div>
{clr?.images?.map((img, imgkey) => {
return (
<div className="form-group pt-3" key={imgkey}>
<input
label="Image"
name="images"
value=""
accept="image/*"
type="file"
fullWidth
required
/>
</div>
);
})}
</div>
);
})}
这里是 codeSandbox 的工作代码。
您应该相应地修改 proClrData 并使用 setProClrData 以触发重新渲染。
你直接更新状态
为此使用函数:
setProClrData(prev => prev.push() // or concat)
您必须调用 setProClrData
函数来更新状态。
记住你不能改变状态,相反你必须提供一个新的引用(在你的例子中是一个新数组)并调用更新函数,否则 React 将不知道应该重新渲染组件。
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
const img = { src: "", imgdata: "" };
const newProClrData = proClrData.map((obj, index) => {
return index !== key ? data : { ...obj, images: [...data.images, img] };
});
setProClrData(newProClrData);
};
问题
您正在改变状态对象,然后 根本 不更新状态。
const addImages = (key) => {
var obj = { src: "", imgdata: "" };
proClrData[key].images = proClrData[key].images.concat(obj); // mutation!!
console.log(proClrData);
};
解决方案
使用您想要的新图像数据对状态更新进行排队。使用功能状态更新从以前的状态更新。浅拷贝 proClrData
数组,对于匹配的元素,也浅拷贝它所以它是一个新的对象引用,然后浅拷贝嵌套的 images
数组并追加新对象。
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
const obj = { src: "", imgdata: "" };
setProClrData(data => data.map((el, i) => i === key ? {
...el,
images: [...el.images, obj],
} : el));
};
由于 React 状态更新是异步处理的,您需要将控制台日志移动到 useEffect
挂钩中以记录状态 它更新后可用下一个渲染。
useEffect(() => {
console.log(proClrData);
}, [proClrData]);
我正在做一个基本的 React 项目,我在其中对对象和数组进行反应状态,我想在这里完成的是我想将对象推送到 images
数组,我想在组件中呈现它,到目前为止,我用谷歌搜索了一些东西,我发现很少有方法可以完成它 array.concat
和 array.push
,我尝试了这两种方法它正在更新状态但它不影响组件
下面是我试过的代码
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
var obj = { src: "", imgdata: "" };
proClrData[key].images = proClrData[key].images.concat(obj);
console.log(proClrData);
};
下面是组件代码
{proClrData.length >= 1 &&
proClrData?.map((clr, key) => {
return (
<div key={key}>
<p className="pt-3 ">{clr.color}</p>
<div className="form-group">
<input
label="Price"
name="price"
value={clr?.price}
type="number"
fullWidth
required
/>
</div>
<div className="form-group pt-3">
<input
label="Quantity"
name="qty"
value={clr?.qty}
type="number"
fullWidth
required
/>
</div>
<div className="text-end pt-3">
<button
variant="contained"
color="primary"
onClick={() => addImages(key)}
>
Add Images
</button>
</div>
{clr?.images?.map((img, imgkey) => {
return (
<div className="form-group pt-3" key={imgkey}>
<input
label="Image"
name="images"
value=""
accept="image/*"
type="file"
fullWidth
required
/>
</div>
);
})}
</div>
);
})}
这里是 codeSandbox 的工作代码。
您应该相应地修改 proClrData 并使用 setProClrData 以触发重新渲染。
你直接更新状态
为此使用函数:
setProClrData(prev => prev.push() // or concat)
您必须调用 setProClrData
函数来更新状态。
记住你不能改变状态,相反你必须提供一个新的引用(在你的例子中是一个新数组)并调用更新函数,否则 React 将不知道应该重新渲染组件。
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
const img = { src: "", imgdata: "" };
const newProClrData = proClrData.map((obj, index) => {
return index !== key ? data : { ...obj, images: [...data.images, img] };
});
setProClrData(newProClrData);
};
问题
您正在改变状态对象,然后 根本 不更新状态。
const addImages = (key) => {
var obj = { src: "", imgdata: "" };
proClrData[key].images = proClrData[key].images.concat(obj); // mutation!!
console.log(proClrData);
};
解决方案
使用您想要的新图像数据对状态更新进行排队。使用功能状态更新从以前的状态更新。浅拷贝 proClrData
数组,对于匹配的元素,也浅拷贝它所以它是一个新的对象引用,然后浅拷贝嵌套的 images
数组并追加新对象。
const [proClrData, setProClrData] = useState([
{ color: "black", price: "", qty: "", images: [] },
{ color: "white", price: "", qty: "", images: [] },
{ color: "red", price: "", qty: "", images: [] }
]);
const addImages = (key) => {
const obj = { src: "", imgdata: "" };
setProClrData(data => data.map((el, i) => i === key ? {
...el,
images: [...el.images, obj],
} : el));
};
由于 React 状态更新是异步处理的,您需要将控制台日志移动到 useEffect
挂钩中以记录状态 它更新后可用下一个渲染。
useEffect(() => {
console.log(proClrData);
}, [proClrData]);