React useState 在对象数组中更改数组中的所有元素



>我有 2 种状态产品和变体,我调用 API 并将两种状态的值设置为 API 响应。

我希望产品状态保持原样,而不是更新

const [product, setProduct] = useState({} as any);
const [variations, setVariations] = useState([] as any);
useEffect(() => {
const getProduct = async () => {
const data = await axios.get("/products?id=4533843820679");
console.log(data);
setProduct(data.data);
// @ts-ignore
setVariations([data.data]);
};
getProduct();
}, []);

作为回报,我映射变体数组并返回标题、价格和添加变体的按钮的输入。添加变体会将另一个产品添加到变体数组。所以它只是将产品推向变体。

然后,我输入了变体中的标题和变体中的价格。问题出在 onChange 上。

当我更改变体中一个元素的价格时,它会更改所有元素的价格,并且还会更改 PRODUCT 状态的价格。

代码可以在这里找到:https://codesandbox.io/s/smoosh-firefly-6n747?file=/src/App.js

添加变体,更改价格添加另一个变体,您将看到我面临的所有问题。

正是因为这个:

variant.price = e.target.value; // same issue with title

variant对象引用在变体之间共享,您直接对其进行修改。之所以共享它,是因为您在添加variation时使用...制作了该副本的浅拷贝。

这是解决方案:

你应该以不可变的方式更新特定的variant对象(在 react 中,你应该始终以不可变的方式更新状态)。为此,您需要将其用作priceonChange

onChange = {
(e) => {
let updated = variations.map((x) => {
if (x.id === variation.id) {
return {
...x,
variants: x.variants.map((y) => {
if (y.id === variant.id) {
return {
...y,
price: e.target.value
};
}
return y;
})
};
}
return x;
});
setVariations(updated);
}
}

这为onChangetitle

onChange = {
(e) => {
let updated = variations.map((x) => {
if (x.id === variation.id) {
return {
...x,
title: e.target.value
};
}
return x;
});
setVariations(updated);
}
}

注意,但变体的 ID 必须不同。出于测试目的,您可以在添加新变体时将其用作点击处理程序:

onClick = {
() => {
setVariations((prev) => [...prev, {
...product,
id: Math.floor(Math.random() * 1000) // for testing
}]);
}
}

首先,您不会将产品推向变体。您正在覆盖它。

要使用 useState 将值推送到数组,

setVariations([...variations, product])

但是,如果您更改产品对象,变体也会更改,因为它是相同的对象。(也许,反应不会重新渲染它,但相信我,它被改变了。如果你想保持它不变,你需要创建新对象。

所以

setProduct(data.data);
setVariations([...variations, {...data.data}]);

现在,您可以更改产品。变体不会更改。

这是因为您做了对象的浅表副本。

尝试这样做:

setVariations([...variations, data.data,]);

相关内容

  • 没有找到相关文章

最新更新