如何在React中使用State(附代码示例)

118 阅读3分钟

自从React钩子发布后,函数组件可以使用状态和副作用。有两个钩子用于React中的现代状态管理:useState和useReducer。本教程将逐步介绍React中的useState例子,让你开始使用这个用于状态管理的React Hook。

React中的简单状态

在过去,状态不能被用于功能组件中。因此,他们称之为功能性无状态组件。然而,随着React Hooks的发布,状态也可以在这种组件中使用,因此它们被React社区重新命名为功能组件。下面的例子演示了如何在函数组件中用useState钩子使用状态的简单例子。

const App = () => {
  const [count, setCount] = React.useState(0);

  const handleIncrease = () => {
    setCount(count + 1);
  };

  const handleDecrease = () => {
    setCount(count - 1);
  };

  return (
    <div>
      Count: {count}
      <hr />
      <div>
        <button type="button" onClick={handleIncrease}>
          Increase
        </button>
        <button type="button" onClick={handleDecrease}>
          Decrease
        </button>
      </div>
    </div>
  );
};

useState函数需要一个初始状态的值作为参数。在这种情况下,计数从0开始。此外,该钩子返回一个包含两个值的数组:countsetCount 。这两个值的命名取决于你,因为它们是从返回的数组中解构出来的,在这里允许重命名。

第一个值,在这里是count ,代表当前状态。第二个值,在这里是setCount ,是一个函数,用于在调用这个函数时用传递给这个函数的任何东西更新状态。这个函数也被称为状态更新函数。每次调用这个函数时,React都会重新渲染组件以呈现新的状态。

你也可以阅读这篇文章,如果你想知道状态管理是如何从类组件变为函数组件的,以防你也在处理类组件。

这就是你在React中开始进行简单的状态管理所需要知道的一切。如果你对React的useState注意事项感兴趣,那么继续阅读。

React中的复杂状态

到目前为止,这个例子只展示了用JavaScript原语的useState。这正是useState的闪光之处。它可以用于整数、布尔、字符串,也可以用于数组。然而,一旦你打算用对象或更复杂的数组来管理更复杂的状态,你应该看看React的useReducer挂钩。在各种情况下,useReducer都要优于useState。

  • 复杂的状态容器
  • 复杂的状态转换
  • 有条件的状态更新

它还有助于通过只使用useState来避免多个连续的状态更新。如果你想在React中管理更复杂的状态,你肯定应该看看它。

React中的异步状态

如果你依赖实际状态来更新状态,会发生什么?让我们用一个例子来说明这个情况,我们用JavaScript内置的setTimeout函数来延迟状态的更新。

const App = () => {
  const [count, setCount] = React.useState(0);

  const handleIncrease = () => {
    setTimeout(() => setCount(count + 1), 1000);
  };

  const handleDecrease = () => {
    setTimeout(() => setCount(count - 1), 1000);
  };

  return (
    <div>
      Count: {count}
      <hr />
      <div>
        <button type="button" onClick={handleIncrease}>
          Increase
        </button>
        <button type="button" onClick={handleDecrease}>
          Decrease
        </button>
      </div>
    </div>
  );
};

每当你点击其中一个按钮,状态更新函数就会被调用,延迟一秒钟。这对单次点击是有效的。然而,试着连续多次点击其中的一个按钮。在这一秒内,状态更新函数将总是对同一个状态(这里是:count )进行操作。为了解决这个问题,你可以从useState传递一个函数给状态更新函数。

import React from 'react';

const App = () => {
  const [count, setCount] = React.useState(0);

  const handleIncrease = () => {
    setTimeout(() => setCount(state => state + 1), 1000);
  };

  const handleDecrease = () => {
    setTimeout(() => setCount(state => state - 1), 1000);
  };

  return (
    <div>
      Count: {count}
      <hr />
      <div>
        <button type="button" onClick={handleIncrease}>
          Increase
        </button>
        <button type="button" onClick={handleDecrease}>
          Decrease
        </button>
      </div>
    </div>
  );
};

export default App;

该函数为你提供执行该函数时的状态。这样,你就不会在任何陈旧的状态上操作。因此,一个好的经验法则可能是:如果你的状态更新依赖于你之前的状态,那么总是在useState的更新函数中使用一个函数。