React state 更新原理(三) - state 快照的总结和实践

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

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

state 变量可能看起来像您可以读取和写入的常规 JavaScript 变量。但是,state 的行为更像是快照。设置它不会更改您已有的 state 变量,而是会触发重新渲染。

这个系列的文章你将学习到:

  • 如何设置 state 的触发器进行重新 render
  • state 何时以及如何更新
  • 设置 state 后为什么状态不会立即更新
  • 事件处理程序如何访问 state 的“快照”

系列文章

总结

  • 设置 state 会进行新的 render。
  • React 将 state 存储在组件之外,就像在架子上一样。
  • 当您调用 useState 时,React 会为您提供这次 render 中 state 的快照。
  • 变量和事件处理程序在 re-render 时不会“幸存”。每次 render 都有自己的事件处理程序。
  • 每次 render(以及其中的函数)将始终“看到”React 赋予该 render 的 state 快照。
  • 你可以在心里替换事件处理程序中的 state,类似于你对 render 出的 JSX 的看法。
  • 过去创建的事件处理程序具有创建它们的时候 render 的 state 值。

实践 - 交通灯切换

学习完了这个系列的三篇文章,我们通过一个例子来加深印象吧~

这是一个人行横道灯组件,当按钮被按下时会切换:

import { useState } from 'react';

export default function TrafficLight() {
  const [walk, setWalk] = useState(true);

  function handleClick() {
    setWalk(!walk);
  }

  return (
    <>
      <button onClick={handleClick}>
        Change to {walk ? 'Stop' : 'Walk'}
      </button>
      <h1 style={{
        color: walk ? 'darkgreen' : 'darkred'
      }}>
        {walk ? 'Walk' : 'Stop'}
      </h1>
    </>
  );
}
复制代码

向单击处理程序添加 alert。当绿灯亮并显示“Walk,”时,点击按钮应该显示“Stop is next.”。当红灯亮并显示“Stop,”时,点击按钮应该显示“Walk is next.”。

把 alert 放在 setWalk调用之前还是之后有区别吗?

3

2

1

解决方式:

import { useState } from 'react';

export default function TrafficLight() {
  const [walk, setWalk] = useState(true);

  function handleClick() {
    setWalk(!walk);
    alert(walk ? 'Stop is next' : 'Walk is next');  // 这里
  }

  return (
    <>
      <button onClick={handleClick}>
        Change to {walk ? 'Stop' : 'Walk'}
      </button>
      <h1 style={{
        color: walk ? 'darkgreen' : 'darkred'
      }}>
        {walk ? 'Walk' : 'Stop'}
      </h1>
    </>
  );
}
复制代码

把它放在 setWalk 调用之前还是之后都没有区别,这次 render 的 walk 值是固定的。调用 setWalk 只会在下一次 render 更改它,但不会影响上一次 render 的事件处理程序。

这行代码乍一看似乎有悖常理:

alert(walk ? 'Stop is next' : 'Walk is next');
复制代码

但是如果你把它读成:“如果红绿灯显示‘Walk now’,那么消息应该是‘Stop is next’。”事件处理程序中的 walk 变量与 render 的 walk 值匹配并且不会改变。

您可以通过替换变量的方法来验证这是否正确。当 walktrue 时,你会得到:

<button onClick={() => {
  setWalk(false);
  alert('Stop is next');
}}>
  Change to Stop
</button>
<h1 style={{color: 'darkgreen'}}>
  Walk
</h1>
复制代码

因此,单击“Change to Stop”会将 walk 设置为 false 的渲染进行排队,并 alert “Stop is next”。

猜你喜欢

转载自juejin.im/post/7035501818989772836
今日推荐