排队更新 state
批处理怎样影响一次事件中的更新?
- 批处理: React 通常等同一事件处理中的更新都提交后再更新 UI,减少中间状态和重复工作;
- 交互边界: 不会把彼此独立的有意点击无条件合并,第一次点击禁用按钮后,下一次点击应看到更新结果;
- 快照不变: 批处理期间读取的变量仍属于当前渲染,原因见 state 快照笔记;
更新函数怎样累计待处理状态?
- 更新函数:
setCount(n => n + 1)描述从队列中前一个结果计算下一值,React 在处理队列时按顺序传入结果; - 连续调用: 三个加一更新函数把 0 依次变为 1、2、3,不依赖当前闭包中的 count;
function incrementThreeTimes() {
setCount((n) => n + 1);
setCount((n) => n + 1);
setCount((n) => n + 1);
}
直接替换与更新函数混用时怎样计算?
- 直接值: 在队列中表达“替换为这个值”,不依赖前一项的计算结果;
- 顺序规则: 替换和更新都按入队顺序执行,后面的替换可以覆盖前面的累计结果;
| 队列项 | 输入 | 输出 |
|---|---|---|
| 替换为 5 | 0 | 5 |
n => n + 1 | 5 | 6 |
| 替换为 42 | 6 | 42 |
setCount(5);
setCount((n) => n + 1);
setCount(42);
更新函数中为什么不能执行副作用?
- 纯计算: 更新函数在渲染过程中参与计算,只返回下一状态,不在里面发请求、触发其他状态更新或修改旧对象;
- 开发检查: StrictMode 可能调用更新函数两次并忽略一次结果,纯函数才能使这种检查不改变业务结果;
- 参数命名: 用
prevCount或清晰的短名表示待处理状态,避免把它误认为永远等于当前闭包中的变量;