学习 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)来管理这些更改。

Source: https://dev.to/bismay-exe/day-5-of-learning-react-understanding-automatic-batching-functional-updates-397k