Skip to content

React Hooks 文档翻译 - 3 - Using the State Hook(使用状态 Hook) #103

Open
@tcatche

Description

@tcatche

本文博客地址:React Hooks 文档翻译 - 3 - Using the State Hook(使用状态 Hook).

翻译自:https://reactjs.org/docs/hooks-state.html

Hooks 是 React 16.8 新增的功能。它允许你在不编写类的情况下使用状态和其他 React 特性。

上一篇文章使用了下面的示例介绍了 Hooks:

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

我们将通过此代码与同样功能的类实现的代码进行比较来学习 Hooks。

Equivalent Class Example

等效的类实现示例

如果你之前在 React 中使用过类,那么这段代码应该很熟悉:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

state 的初始状态为 { count: 0 } ,当用户单击按钮调用 this.setState() 时,会增加 state.count 。我们将在整个页面中使用此类的片段。

Note

你可能想知道为什么我们使用计数器而不是更真实的例子。这是为了我们在 Hooks 迈出第一步时能够更专注于API。

Hooks and Function Components

Hooks 和函数组件

提醒一下,React 中的函数组件如下所示:

const Example = (props) => {
  // You can use Hooks here!
  return <div />;
}

或者:

function Example(props) {
  // You can use Hooks here!
  return <div />;
}

你可能以前称之为“无状态组件”。现在我们为它们引入了使用 React state 的能力,所以我们更喜欢“函数组件”的名称。

Hooks 在类里不起作用。你可以使用它们而不用再编写类组件。

What's a Hook?

什么是 Hooks?

我们的新示例首先从 React 中引入 useState Hook:

import { useState } from 'react';

function Example() {
  // ...
}

什么是 Hook? Hook 是一种特殊功能,可以让你“挂钩到” React 的一些功能。例如,useState 就是一个 Hook,允许你将 React 的状态添加到函数组件。我们稍后会学习其他的 hooks。

我什么时候使用 Hook? 如果你写了一个函数组件并意识到需要为它添加一些状态,如果在以前,你必须将它转换为一个类。现在,你可以在现有的函数组件中使用 Hook。就像我们现在这么做的!

Note:

关于在何处可以或者不可以使用 Hook ,有一些特殊规则。我们可以在Hooks 的规则中学习它们。

Declaring a State Variable

声明一个状态变量

在类中,我们初始化 count 状态为 0 通过在构造器中设置 this.state 的值为 { count: 0 }

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

函数组件中没有 this ,因此,不能设置或者读取 this.state ,相反,我们直接在组件中调用 useState Hook。

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

调用 useState 做了什么? 它声明了一个“状态变量”。我们的变量叫做 count ,也可以叫其他任何名字,比如 banana 。这是一种在函数调用间“保留”某些值的方法 -- useState 是一种新方法,可以提供和类中 this.state 完全相同的功能。通常,当函数结束时变量“消失”但 React 可以为我们保留“状态变量”。

我们传递给 useState 的参数是什么? useState() Hook 的唯一参数是初始状态值。与类不同,状态不必是对象。如果需要的话,可以设置为一个数字或字符串。在示例中,我们只需要一个数字来表示用户点击的次数,因此传入 0 作为变量的初始状态。(如果我们想在状态中存储两个不同的值,可以调用 useState() 两次。)

useState 返回值是什么? 它返回了一对值:当前状态值和更新状态值的函数。这就是我们写 const [count, setCount] = useState()。它与类中的 this.state.countthis.setState 类似,只不过它们是成对的。如果你不熟悉我们使用的方括号语法(即数组解构,译者注),我们将在本页底部回顾它

现在,了解了 useState Hook的作用,我们的例子就更容易理解:

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

We declare a state variable called count, and set it to 0. React will remember its current value between re-renders, and provide the most recent one to our function. If we want to update the current count, we can call setCount.

我们声明一个名为 count 的状态变量,并将其设置为 0。 React 能记住它在多次渲染时的当前值,并为组件提供了最新的值。如果想要更新当前计数值 count ,可以调用 setCount

Note

你可能想知道:为什么 useState 没有命名为 createState

“创建”不很准确,因为状态仅在组件首次渲染时创建。在下一次渲染时,useState 提供了当前的状态值,否则它根本不会是“状态”!Hooks 名称总是使用开始也是有原因的。我们将在后面的 Hooks 的规则 中了解它。

Reading State

读状态

当我们想要在类组件中显示当前计数时,通过 this.state.count 读取值:

  <p>You clicked {this.state.count} times</p>

在函数组件中,可以直接使用 count

  <p>You clicked {count} times</p>

Updating State

更新状态

In a class, we need to call this.setState() to update the count state:

在类组件中,需要调用 this.setState() 来更新 count 状态值:

  <button onClick={() => this.setState({ count: this.state.count + 1 })}>
    Click me
  </button>

在函数组件中,已经有了 setCountcount 变量,不需要再使用 this:

  <button onClick={() => setCount(count + 1)}>
    Click me
  </button>

Recap

概括

现在,我们通过下面代码逐行概括我们学习到的内容,并检查我们的理解。

  import { useState } from 'react';
 
  function Example() {
    const [count, setCount] = useState(0);

    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
         Click me
        </button>
      </div>
    );
  }
  • 第1行:我们从 React 引入 useState Hook。它允许我们将本地状态保存在函数组件中。
  • 第4行:在 Example 组件内部,通过调用 useState Hook 声明一个新的状态变量。它返回一对值到给它们的命名上。我们调用变量计数 count,它保存了按钮点击次数。我们将其值初始化为零,通过传递 0 作为 useState 的唯一参数。第二个返回项是一个函数,它可以用来更新计数 count,因此我们将其命名为 setCount
  • 第9行:当用户点击时,使用新值调用 setCount。然后,React 将重新渲染 Example 组件,并将新计数值传递给它。

开始,看起来似乎需要考虑很多东西,不要急于求成!如果你被上面的解释迷糊了,请再次查看上面的代码并尝试逐行阅读。我们保证,一旦你“忘记”了状态如何在类上工作,并以新的眼光看待这个代码,就会很容易理解。

Tip: What Do Square Brackets Mean?

提示:方括号语法什么意思?

当声明一个状态变量时,你可能已经注意到了方括号:

  const [count, setCount] = useState(0);

左侧的名称不是 React 的 API。你可以随便命名自己的状态变量:

  const [fruit, setFruit] = useState('banana');

This JavaScript syntax is called "array destructuring". It means that we're making two new variables fruit and setFruit, where fruit is set to the first value returned by useState, and setFruit is the second. It is equivalent to this code:

这段 JavaScript 语法称为“数组解构”。它的意思是创建两个新变量 fruitsetFruit ,其中 fruit 设置为 useState 返回的数组的第一个值,setFruit 是数组的第二个值。它等价于这段代码:

  var fruitStateVariable = useState('banana'); // Returns a pair
  var fruit = fruitStateVariable[0]; // First item in a pair
  var setFruit = fruitStateVariable[1]; // Second item in a pair

当使用 useState 声明一个状态变量时,返回一个包含两个项的数组。第一项是当前值,第二项是允许更新它的函数。使用 [0][1] 访问它们有点令人困惑,因为它们有着特定含义。这就是在这里使用数组解构的原因。

Note

你可能很好奇, React 如何知道 useState 和组件的对应关系,因为并没有将像 this 这样的任何内容传递给 React。我们将在FAQ部分回答这个问题以及许多其他问题。

Tip: Using Multiple State Variables

提示:使用多个状态变量

将状态变量声明为一对 [something,setSomething] 的结构也很方便,因为如果我们想要多个状态变量,可以很方便的为不同的状态变量赋予不同的名称:

function ExampleWithManyStates() {
  // Declare multiple state variables!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

在上面的组件中,agefruittodos 作为局部变量,可以单独更新它们:

  function handleOrangeClick() {
    // Similar to this.setState({ fruit: 'orange' })
    setFruit('orange');
  }

不是必须使用多个状态变量。状态变量也可以很好地保存在对象和数组中,因此你仍然可以将相关数据组合在一起。但是,与类中的 this.setState 不同,更新状态变量总是替换它而不是合并它。

我们在FAQ中提供了有关拆分独立状态变量的更多建议。

Next Steps

下一步

本文,我们了解了 React 提供的名为 useState 的 Hook。有时也会称为“状态 Hook”。它允许我们将内部状态添加到 React 函数组件 -- 历史上第一次可以这样做!

我们还了解了更多关于 Hooks 是什么的内容。Hooks 让你从函数组件“挂钩” React 的功能。它们的名字总是从 use 开始,并且还有其它更多还没见过的钩子。

**现在让我们继续学习下一个 Hook:useEffect。**它允许你在组件中执行副作用的操作,类似类组件中的生命周期方法。

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions