了解React中设置状态的代码流程



我有这个基本的代码,从处理程序更新状态:

const wait = (ms) => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};
export default function App() {
async function handleClick() {
setData(1);
console.log("first click");
console.log(data);
await wait(1000);
setData(2);
console.log("second click");
console.log(data);
}
const [data, setData] = React.useState(0);
return (
<div>
{data}&nbsp;
<button onClick={() => handleClick(setData)}>Click Me</button>
</div>
);
}

我正试图理解操作的顺序,有人可以验证或指出我在正确的方向发生了什么?我四处研究了一下,但还没有找到我认为发生的事情的决定性来源。

  1. 我们点击按钮,触发处理程序
  2. 处理程序运行setData(1),将任务排队到事件循环
  3. console.log('first click')运行
  4. 我们记录状态(数据),它仍然是0,因为setter刚刚进入队列
  5. 我们运行到等待函数,所以我们退出到同步代码流,因为我们等待1000ms
  6. 同步代码完成运行,所以我们取消下一个任务的队列,这是setter函数,状态现在被设置为1,并且视图重新呈现并反映新状态
  7. 1秒后,我们返回到代码后等待函数
  8. setData(2)正在排队等待另一个任务
  9. 'second click'被记录
  10. 0仍然被记录,因为我们的本地状态没有改变
  11. 同步代码完成,我们取消setter的队列,重新渲染视图,导致2显示

这些都对吗?我有误解什么吗?谢谢你的帮助。

是的,你写对了,除了那个

运行setData(1),将任务排队到事件循环

这可能涉及也可能不涉及事件循环。setData中发生的事情是特定于react.js的,并且不一定会在浏览器事件循环中为任务排队。"不知怎么的",它确实是这样的。在react中安排组件的状态更新和重新呈现。

如果我没记错的话,react.js确实安排了由setData(1)引起的渲染,用于本机点击处理程序的结束,即当对onClick处理程序的调用返回到react代码时。对于setData(2),呈现实际上可能在setData调用中同步发生,因为react不控制上下文。然而,这可能会发生变化(开发者正在讨论将多个更新异步地批处理在一起),并且应该被视为实现细节。如果您很好奇,只需在组件的呈现函数中放置一个console.log,但不要编写任何依赖于此测试中观察到的顺序的代码!

最新更新