React state 更新队列(二) - 在下一次 render 之前多次更新相同的 state

这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

翻译自:beta.reactjs.org/learn/queue…

设置 state 的值引起另一个 render 队列。但有时你可能希望执行下一次 render 队列之前对值执行多个操作。为了这样做,这篇文章有助于了解 React 如何批量更新状态。

你将会学习到:

  • 什么是“批量处理(batching)”,React 如何使用它来处理多个 state 更新
  • 如何在一行中对同样的 state 应用几个更新

系列文章

这是一个系列的文章,希望你能从头看,因为它们的例子之间会有先后关系的~

在下一次 render 之前多次更新相同的 state

上一篇文章我们说到,React 像一个餐厅的服务员,会等待事件处理程序中的所有代码运行后再处理 state 更新,如果我们在一个事件处理程序中多次执行 setNumber(number + 1),实际生效的也只有一次的效果,就像我们在餐厅中跟服务员说了三次,我要点鱼香肉丝一样。

这是一个不常见的用例,但是如果你想在下一次渲染之前多次更新相同的状态变量,实现时就不是像 setNumber(number + 1) 这样传递下一个状态值,你可以传递一个函数,该函数根据队列中的前一个状态计算下一个状态。像 setNumber(n => n + 1),这是一种告诉 React “用状态值做某事”而不是仅仅替换它的方法。

现在我们对上一篇文章中的例子做一些修改,尝试增加计数器:

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(n => n + 1);
        setNumber(n => n + 1);
        setNumber(n => n + 1);
      }}>+3</button>
    </>
  )
}
复制代码

你会发现,点击按钮后,可以一次的增加3。

这里,n => n + 1 被称为 updater function。当你将它传递给 state 的 setter 时:

  • 在事件处理程序中的所有其他代码运行后,React 将此函数排入队列以进行处理。
  • 在下一次渲染期间,React 遍历队列并为您提供最终更新状态。
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
复制代码

下面是 React 在执行事件处理程序时如何通过这几行代码工作的:

  • setNumber (n => n + 1): n => n + 1 是一个函数。 React 将其添加到队列中。
  • setNumber (n => n + 1): n => n + 1 是一个函数。 React 将其添加到队列中。
  • setNumber (n => n + 1): n => n + 1 是一个函数。 React 将其添加到队列中。

当你在下一次渲染期间调用 useState 时,React 会遍历队列。之前的数字状态是 0,所以 React 将它作为 n 参数传递给第一个更新器函数。然后 React 将您之前更新程序函数的返回值作为 n 传递给下一个更新程序,依此类推:

更新队列 n 返回值
n => n + 1 0 0 + 1 = 1
n => n + 1 1 1 + 1 = 2
n => n + 1 2 2 + 1 = 3

React 存储 3 作为最终结果并从 useState 返回它。

这就是为什么在上面的示例中单击“+3”正确地将值增加 3。

猜你喜欢

转载自juejin.im/post/7032926737461837854