意外状态更新导致“useState”函数
Posted
技术标签:
【中文标题】意外状态更新导致“useState”函数【英文标题】:Unexpected state update results in "useState" function 【发布时间】:2021-12-20 18:06:53 【问题描述】:考虑这个使用函数更新useState
对象的简单示例:
App.tsx
import useState from 'react';
export default function App()
const [state, setState] = useState(
id: 0,
);
const update = () =>
setState(prev =>
const id = Date.now();
console.log('previous id:', prev.id, 'new id:', id);
return
id,
;
);
;
return (
<div>
<div>state: JSON.stringify(state)</div>
<button onClick=update>Update</button>
</div>
);
将其放入标准的 create-react-app typescript 模板(使用 React 17.0.2),并在开发模式下运行应用程序。继续单击更新按钮并观察控制台。很快就会遇到预期状态和实际状态之间的差异,例如
previous id: 1636301326090 new id: 1636301326260
previous id: 1636301326260 new id: 1636301326440
previous id: 1636301326440 new id: *1636301326611*
previous id: *1636301326612* new id: 1636301326804 // What???
previous id: 1636301326804 new id: 1636301326997
在上面的控制台日志中,id: 1636301326612
状态突然出现,因为设置的状态是 id: 1636301326611
。
更奇怪的是,当应用程序是为生产而构建时,我无法重现这一点。此外,如果我放弃功能更新并仅将对象传递给setState
,就像注释掉的代码一样(由于原子性要求,在我的实际非玩具代码中不可行),问题似乎也不存在。
我完全不知所措。我是否以某种方式使用了setState
错误?
如有必要,我可以提供完整的示例 repo。
【问题讨论】:
【参考方案1】:这可能是因为在开发中,setState 在严格模式下被调用了两次。 设置状态值不取决于先前的值,而是取决于时间。这是副作用。
相关链接https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects https://github.com/facebook/react/issues/12856
【讨论】:
太好了,所以基本上在下一个状态设置新日期是React
试图在strict-mode
中捕获的杂质,谢谢。
谢谢!我实际上发现这是严格模式双重调用该方法(计划自己提交答案但太忙),但文档链接非常有帮助。我已经阅读了该页面,但不知何故错过了这个非常重要的部分,facepalm。如果不是抑制console.log
,而是将其修改为打印“从严格模式双重调用函数:...”,这可能会更有帮助。以上是关于意外状态更新导致“useState”函数的主要内容,如果未能解决你的问题,请参考以下文章