如果对象引用未更改,则 useState 正在接受更新
useState is accepting updates if the object reference does not change
我认为 useState
需要一个新值才能接受更新:
我创建了这个codesandbox 来说明我的意思。
我有一个这样的嵌套数据结构
const state = {
name: "parent",
data: {
isExpanded: false,
children: [
{ name: "one", data: { isExpanded: false } },
{ name: "two", data: { isExpanded: false } },
{ name: "three", data: { isExpanded: false } }
]
}
};
然后我使用 useState
在状态改变时引起重新渲染:
function App() {
const [tree, setTree] = useState(state);
const toggleExpanded = node => {
node.data.isExpanded = !node.data.isExpanded;
setTree(tree);
};
return (
<div className="App">
<h1>IsExpanded</h1>
{tree.data.children.map(child => (
<button onClick={() => toggleExpanded(child)}>
{child.name} - {child.data.isExpanded ? "on" : "off"}
</button>
))}
</div>
);
}
我每次调用 setTree
时都使用相同的引用并且正在进行更新。
我认为每次都需要一个新的引用才能发生这种情况?
我可能遗漏了一些东西,但更新没有发生在同一个参考文献上。
最好使用不可变状态,因为这种方法是 React 惯用的。但这也适用于改变现有状态。 setTree(tree)
触发更新,tree
相同或不同无关紧要。
与setState(sameState)
在class组件中的作用相同,与forceUpdate
类似,一般不提倡。
这是预期的行为。 useState
返回的 setter 在这方面与非钩子 setState
的工作方式相同。它的任何执行都会触发重新渲染,并且它是否是相同的对象引用并不重要。
如果你刚刚做了:
node.data.isExpanded = !node.data.isExpanded;
如果不调用 setTree
,则不会发生视觉更新,因为不会触发重新渲染。
通常建议避免通过更改现有状态对象来进行状态更新,因为这可能会导致某些类型的错误(例如,如果您有任何将先前状态与新状态进行比较的逻辑,它们似乎总是如果您通过改变现有对象进行更改,则相同)。这可能导致的微妙问题可能会随着未来的 React 并发模式功能而扩展,但 React 不会阻止您这样做。
我认为 useState
需要一个新值才能接受更新:
我创建了这个codesandbox 来说明我的意思。
我有一个这样的嵌套数据结构
const state = {
name: "parent",
data: {
isExpanded: false,
children: [
{ name: "one", data: { isExpanded: false } },
{ name: "two", data: { isExpanded: false } },
{ name: "three", data: { isExpanded: false } }
]
}
};
然后我使用 useState
在状态改变时引起重新渲染:
function App() {
const [tree, setTree] = useState(state);
const toggleExpanded = node => {
node.data.isExpanded = !node.data.isExpanded;
setTree(tree);
};
return (
<div className="App">
<h1>IsExpanded</h1>
{tree.data.children.map(child => (
<button onClick={() => toggleExpanded(child)}>
{child.name} - {child.data.isExpanded ? "on" : "off"}
</button>
))}
</div>
);
}
我每次调用 setTree
时都使用相同的引用并且正在进行更新。
我认为每次都需要一个新的引用才能发生这种情况?
我可能遗漏了一些东西,但更新没有发生在同一个参考文献上。
最好使用不可变状态,因为这种方法是 React 惯用的。但这也适用于改变现有状态。 setTree(tree)
触发更新,tree
相同或不同无关紧要。
与setState(sameState)
在class组件中的作用相同,与forceUpdate
类似,一般不提倡。
这是预期的行为。 useState
返回的 setter 在这方面与非钩子 setState
的工作方式相同。它的任何执行都会触发重新渲染,并且它是否是相同的对象引用并不重要。
如果你刚刚做了:
node.data.isExpanded = !node.data.isExpanded;
如果不调用 setTree
,则不会发生视觉更新,因为不会触发重新渲染。
通常建议避免通过更改现有状态对象来进行状态更新,因为这可能会导致某些类型的错误(例如,如果您有任何将先前状态与新状态进行比较的逻辑,它们似乎总是如果您通过改变现有对象进行更改,则相同)。这可能导致的微妙问题可能会随着未来的 React 并发模式功能而扩展,但 React 不会阻止您这样做。