我在 React 中遇到了状态更新的特殊问题,这不是一个错误,我的代码工作正常,但我感觉有点奇怪。最初,我有一个产品状态,其中包含从 API 获取的所有产品:
const [products, setProducts] = useState<Product[]>([]);
我创建了一个更改产品信息的功能。尽管我没有更新之前产品的状态,但描述仍然更改为新产品:
const handleChangeProduct = async ({ productId }: Product) => {
const exitsProduct = products.find(({ id }) => id === productId);
exitsProduct.description = "example desc";
const response = await fetch(
`${process.env.VITE_APP_API_URL}/products/add`,
{
method: 'POST',
body: JSON.stringify(exitsProduct),
}
);
const responseObj = await response.json();
// Update the products state, I don't know why the products state is update the description to `example desc`.
if (responseObj?.success) {
setProducts(products);
}
}
自从我开始使用 React 以来,这是我认为更新状态的正确方法。
const updatedProducts = products.map((product) => {
if (product.id === productId) {
return {
...product,
description: product.description,
}
}
return product;
});
setProducts(updatedProducts);
如果这是由于我对 ReactJS 缺乏了解,请告诉我。即使我们将状态复制到新常量,我们实际上可以更新新产品状态吗?
我想你知道所示的
handleChangeProduct
打破了React状态的基本规则:不要直接修改状态成员。我想您是在问,如果函数做错了,为什么您会看到更新的描述。
这是因为React可能会因为其他原因重新渲染你的组件,并且在重新渲染时,它会使用state中对象的当前属性,包括错误更新的属性。错误更新它们的问题在于,无法保证 React 何时或是否会呈现您所做的更改。为了正确确保 React 呈现更改,您需要执行
updatedProducts
函数的操作:创建一个新数组,并为要更新的产品创建一个新对象。
旁注:
setProducts(products);
中的 handleChangeProduct
调用不会执行任何操作,因为 products
(数组)没有更改(至少在显示的代码中没有更改),即使其中一个对象的属性数组中的内容已更改。