学习 React 第 5 天:批处理与函数式更新
我原以为多次调用状态设置函数(state setter)会导致多次渲染。
我错了。
React 比这要聪明得多。它使用一种称为“自动批处理”(Automatic Batching)的过程。
React 不会在每次更新后都进行渲染,而是将它们组合在一起。它收集所有更新并执行一次渲染。这可以提升性能。
以下是我今天学到的内容。
批处理过程
当你调用多个状态函数时,React 会遵循以下流程:
- 发生多次状态更新。
- React 将它们进行批处理。
- React 执行一次渲染。
- React 将更改提交到 UI。
标准更新的问题
我尝试了这段代码:
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
我预期 count 会从 0 变为 3。 结果它从 0 变成了 1。
这是因为 setCount(count + 1) 的意思并不是“增加计数”。
它的意思是“将计数设置为这个特定的值”。
如果 count 是 0,每一行都在告诉 React 将 count 设置为 1。React 对这些操作进行批处理,并发现最终的指令是将 count 设置为 1。
解决方案:函数式更新
要解决这个问题,你必须使用函数式更新。它会使用更新队列中最新的可用状态。
正确的方法:
setCount((prev) => prev + 1);
当你使用这种模式时,React 会为每次更新提供最新的值。
- 第一次更新:0 + 1 = 1
- 第二次更新:1 + 1 = 2
- 第三次更新:2 + 1 = 3
现在计数器确实达到了 3。
一个常见的错误
我曾经这样写:
setCount((prev) => { prev + 1 });
计数器变成了 undefined。
当你在箭头函数中使用花括号时,必须使用 return 关键字。
请改用这种方式:
setCount((prev) => prev + 1);
核心要点:
- React 通过批处理多次状态更新来提高速度。
setState调用并不总是会立即触发渲染。- 标准更新使用的是当前渲染周期中的值。
- 函数式更新使用的是更新队列中最新的状态。
- React 使用内部的更新队列(Update Queue)来管理这些更改。
