阅读有关useState
钩子的问题 我在想setState
.我总是故意使用带有回调选项的setState
来访问以前的状态,并将所有元素放在数组中。
因此,我为功能组件中的表示做了一个简单的示例:
const [elems, setElems] = useState([]);
const addElemsMutate = (count) => {
const newArray = [...elems];
for (let i = 0; i < count; i++) {
newArray.push(i);
}
setElems(newArray);
};
const addElemsUsePreviousState = (count) => {
for (let i = 0; i < count; i++) {
setElems(previousElems => [...previousElems, i]);
}
}
return <>
<button onClick={() => addElemsMutate(10)}>addElemsMutate</button>
<button onClick={() => addElemsUsePreviousState(10)}>addElemsUsePreviousState</button>
{elems.map((e, index) => <span key={index}>{e}</span>)}
</>
问题
我知道setState
是异步的,排队更改,并且不应像文档所述直接更改。
结果窗体这两个操作在 UI 上看起来相同。所以我的问题是关于我在addElemsMutate
函数中有什么:
- 这被认为是一种不好的做法吗?
- 如果我仍然使用该选项(如果有的话(,缺点是什么?
谢谢!
这里发生了很多可能不是故意的:
- 正如评论中提到的,
addElemsMutate()
实际上并没有改变状态。 addElemsUsePreviousState()
count
状态更改排队,而不是由addElemsMutate()
调度的单个更改。
您可以将useState()
的回调形式与useCallback()
结合使用,作为小型性能优化。
const addElemsCallback = useCallback(count => {
setElems(elems => {
const newElems = [...elems];
for (let i = 0; i < count; i++) {
newElems.push(i);
}
return newElems;
});
}, [setElems]);
由于setElems
永远不会改变,addElemsCallback
也不会改变,这是你唯一需要作为依赖项传递的东西。
React 更改状态的最佳实践是将当前状态复制到新变量中,在那里进行更改,然后更改状态(就像您在示例中所做的那样(。
这是因为,当您直接更改状态时,而不是深度复制以前的状态,您会遇到引用问题,这可能会留下一些难以找到的错误。