考虑这个使用函数更新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 打字稿模板(使用 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。