My App

异步更新

异步更新

好的,是时候来讨论我们第一个基于状态的失误(footgun)了吗

考虑以下代码。当用户第一次点击按钮时,您期望在开发者控制台看到什么值?

function App() {
  const [count, setCount] = React.useState(0);
 
  return (
    <>
      <p>You've clicked {count} times.</p>
      <button
        onClick={() => {
          setCount(count + 1);
 
          console.log(count);
        }}
      >
        Click me!
      </button>
    </>
  );
}

答案是0, 挺奇怪的,对吧?

当我们创建状态变量时,我们将其初始化为 0 。然后,当我们点击按钮时,我们将其增加 1,变为 1 。那么它不应该记录 1 吗,而不是 0 ?

问题在于:状态设置器不是即时的。

当我们调用 setCount 时,我们告诉 React 我们希望请求对状态变量的更改。React 并不会立即中断一切;它会等到当前操作完成(处理点击)后,再更新值并触发重新渲染。

目前,重要的是要知道更新状态变量是异步的。它影响下一个渲染时的状态。它是一个计划的更新。

这是修复代码的方法,以便我们可以立即访问更高的值:

function App() {
  const [count, setCount] = React.useState(0);
 
  return (
    <>
      <p>You've clicked {count} times.</p>
      <button
        onClick={() => {
          const nextCount = count + 1;
          setCount(nextCount);
 
          console.log(nextCount);
        }}
      >
        Click me!
      </button>
    </>
  );
}

我们不是直接将该表达式传递给状态设置函数 setCount(count + 1) ,而是通过将其存储在一个变量中来“保存”它。然后,我们可以在我们的 console.log 语句中使用该变量,或者在这个 onClick 处理程序的其他任何地方使用它。

我喜欢使用前缀“next”,像 nextCount 或 nextUser ,因为它传达了我们在谈论状态的未来值,即在下次渲染时它将会是什么。最终,这只是我个人的偏好。你可以随便给这些变量命名。

为什么会这样工作?

考虑到这是一个如此常见的障碍,值得问一下为什么它是这样设置的。如果 React 立即更新状态变量不是更简单吗?

让我们谈谈这个。

这是视频中的沙盒:

import React from 'react';

function App() {
  const [user, setUser] = React.useState({ name: 'Alyssa' });
  const [status, setStatus] = React.useState('ready');
  const [confirmationMessage, setConfirmationMessage] = React.useState();

  if (!user) {
    return <p>{confirmationMessage}</p>;
  }

  return (
    <button
      onClick={() => {
        setUser(null);
        setStatus('initial');
        setConfirmationMessage("You have been logged out.");
      }}
    >
      Log Out
    </button>
  );
}

export default App;

On this page