react的state是一张快照

时间:2024-10-20 07:41:08

快照的概念

在 React 中,state 是组件状态的表现形式,它是一个组件内部可变的状态数据。React 的官方文档中提到 state 是一个快照(snapshot),这个概念主要是指 React 的状态更新机制

当你调用 setState 方法来更新组件的状态时,React 会异步地将这些更新排队。这意味着,当你在调用 setState 后立即读取 state,你可能会得到旧的 state 值,而不是你刚刚设置的新值。这是因为 React 可能还没有应用这个更新。

import { useState } from 'react';

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

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+3</button>
    </>
  )
}

上面的例子,最终输出的结果是什么呢?

React 函数组件 Counter 中,有一个按钮用于增加状态 number 的值。当按钮被点击时,会触发 onClick 事件处理函数,在该函数中连续三次调用 setNumber(number + 1)

由于 React 的状态更新(通过 setNumber)是异步的,这些更新会被放入一个队列中,然后 React 将它们批量处理以提高性能。这意味着,尽管你在事件处理函数中连续三次调用了 setNumber,实际的状态更新可能不会立即发生,而是会被合并和延迟处理。

具体到这个例子中,尽管你调用了三次 setNumber,React 会将这些更新合并,最终只增加一次状态值,因为最后一次状态更新覆盖了前两次的更新。所以,即使按钮上写的是 “+3”,实际上 number 状态只增加了 1。

至于何时执行更新,React 通常会在当前的事件循环结束后异步执行状态更新。这意味着,如果用户界面在执行 setNumber 调用时是响应的,那么状态更新和组件重新渲染会在浏览器的下一次绘制周期中进行,通常是在当前执行栈清空并且宏任务(如 setTimeoutrequestAnimationFrame)队列为空时。这样可以确保在更新发生前,用户的操作已经被处理完毕,从而提高应用的响应性和性能。

如果你希望每次点击都能使 number 增加 3,你需要这样写 setNumber 的调用:

<button onClick={() => {
  setNumber(n => n+1)
   setNumber(n => n+1)
    setNumber(n => n+1)
}}>+3</button>

总结

  • 设置 state 不会更改现有渲染中的变量,但会请求一次新的渲染。
  • React 会在事件处理函数执行完成之后处理 state
  • 更新。这被称为批处理。 要在一个事件中多次更新某些 state,你可以使用 setNumber(n => n + 1) 更新函数。