使用 useState 更新深层嵌套状态无法正常工作
Updating deeply nested state with useState not working properly
我按照此线程中的答案尝试在 React 中更新我的深层嵌套对象。
那里似乎很有魅力的东西,在执行以下操作时会以某种方式破坏我:
我有一个 table 填充了如下定义的数组中的项目:
const [items, setItems] = useState([
{
selected: false,
title: 'Item 1',
status: 'new'
},
{
selected: false,
title: 'Item 2',
status: 'used'
},
]);
从该列表中选择一个项目时,将调用此函数来为索引为 i
的对象更新 selected
变量,如下所示:
const select = (e) => {
const i = e.target.getAttribute('data-index');
setItems((prevState) => {
prevState[i].selected = !prevState[i].selected;
return [...prevState];
});
};
这只会工作一次。如果我第二次触发 select
或之后的任何时间 return [...prevState]
以某种方式保持返回状态不变。 (selected
永远保持 true
)。我无法解决这个问题。
items
附加到组件 List
,如下所示:
<List
items={items}
/>
和 List
内部(缩写代码):
{items.map((item, i) => {
return (
<tr className="list-table-tr">
{hasSelector ? (
<td className="list-table-td-selector">
{item.selected ? (
<div
data-index={i}
className="global-selector-selected"
onClick={select}
></div>
) : (
<div
data-index={i}
className="global-selector-unselected"
onClick={select}
></div>
)}
</td>
) : null}
您违反了 React 状态的主要规则之一:您正在直接修改状态对象,而不是制作副本。
要正确执行更新,您需要这样做:
const select = (e) => {
const i = e.target.getAttribute('data-index');
setItems((prevState) => {
// Copy the array (your code was doing that)
const update = [...prevState];
const item = update[i];
// Copy the object (your code wasn't doing that) and update its
// `selected` property
update[i] = {...item, selected: !item.selected};
return update;
});
};
注意如何数组和对象被复制,而不仅仅是数组。
我按照此线程中的答案尝试在 React 中更新我的深层嵌套对象。
那里似乎很有魅力的东西,在执行以下操作时会以某种方式破坏我:
我有一个 table 填充了如下定义的数组中的项目:
const [items, setItems] = useState([
{
selected: false,
title: 'Item 1',
status: 'new'
},
{
selected: false,
title: 'Item 2',
status: 'used'
},
]);
从该列表中选择一个项目时,将调用此函数来为索引为 i
的对象更新 selected
变量,如下所示:
const select = (e) => {
const i = e.target.getAttribute('data-index');
setItems((prevState) => {
prevState[i].selected = !prevState[i].selected;
return [...prevState];
});
};
这只会工作一次。如果我第二次触发 select
或之后的任何时间 return [...prevState]
以某种方式保持返回状态不变。 (selected
永远保持 true
)。我无法解决这个问题。
items
附加到组件 List
,如下所示:
<List
items={items}
/>
和 List
内部(缩写代码):
{items.map((item, i) => {
return (
<tr className="list-table-tr">
{hasSelector ? (
<td className="list-table-td-selector">
{item.selected ? (
<div
data-index={i}
className="global-selector-selected"
onClick={select}
></div>
) : (
<div
data-index={i}
className="global-selector-unselected"
onClick={select}
></div>
)}
</td>
) : null}
您违反了 React 状态的主要规则之一:您正在直接修改状态对象,而不是制作副本。
要正确执行更新,您需要这样做:
const select = (e) => {
const i = e.target.getAttribute('data-index');
setItems((prevState) => {
// Copy the array (your code was doing that)
const update = [...prevState];
const item = update[i];
// Copy the object (your code wasn't doing that) and update its
// `selected` property
update[i] = {...item, selected: !item.selected};
return update;
});
};
注意如何数组和对象被复制,而不仅仅是数组。