JavaScript / 前端 / 译文 · 10月 7, 2020 0

React v16.8.x – State Hook

前面的例子介绍了Hooks的例子:

import React, { 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,并且和类进行比较。

类实现

用类实现上面的例子:

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。我们将在整个页面中使用此例子。

注意
您可能想知道为什么我们在这里使用计数器而不是更现实的例子。是为了帮助我们专注于API,同时我们仍在使用Hooks迈出第一步。

Hooks 和函数组件

函数组件一般是声明式或者ES6的箭头函数式。

我们可能以前将这些称为“无状态组件”。我们现在介绍让这些也可以使用React状态的能力,所以我们更喜欢名称“function components”。

hooks在类内不起作用。但是你可以使用它们而不是编写类。

什么是 Hook

首先从react 中导入Hook:

import React, { useState } from 'react';

function Example() {
  // ...
}

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

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

注意
这里有一些特殊的规则,关于你在哪里可以使用Hook并且哪里不能使用Hooks。

声明一个state

类中,这样声明state:

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

函数式组件没有this,无法读取this.state。我们可以直接在函数组件中用useState hook:

import React, { useState } from 'react';

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

}

为什么叫useState 它声明了一个状态。我们的状态变量叫count,但是我们可以任意给这个状态起名字。这是一种在函数调用中保留值的方法,useState能够完美实现类中state的所有功能。通常情况下,当函数执行完毕时变量“消失”,但React保留状态变量。

为什么给 useState 传递一个参数? 参数是状态的初始值。不像类,这个状态不用是一个对象。你想让他是什么它就是什么。我们的例子里它是一个数字,初始值是0.如果你想存放两个不同的值,你需要多次调用useState.

useState返回了什么? 返回一对值:当前的状态和更新状态的函数。所以我们需要这样写const [count, setCount] = useState(). 。这和this.statethis.setState相似。

现在使用hooks改写例子:

import React, { useState } from 'react';

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

声明一个状态count,初始值为0。React 会在重新渲染期间,记住这个变量的值,并将最新值提供给函数组件。如果想更新状态,应调用setCount

注意
为什么是useState而不是creatState?重新渲染期间,并没有创建新的值,而是使用。

使用state

很简单,函数组件没有this,直接使用即可:

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

更新状态

类中,我们使用this.setState,在函数组件中:

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

总结

总结一下:

 1:  import React, { useState } from 'react';
 2:
 3:  function Example() {
 4:    const [count, setCount] = useState(0);
 5:
 6:    return (
 7:      <div>
 8:        <p>You clicked {count} times</p>
 9:        <button onClick={() => setCount(count + 1)}>
10:         Click me
11:        </button>
12:      </div>
13:    );
14:  }
  • 第1行,引入
  • 第4行,定义状态名为count,更新函数名为setCount
  • 第9行,点击触发更新函数,更改状态,视图变化。

起初知识点看起来似乎很多。别急!如果您在解释中迷失了,请尝试从上到下阅读并再次查看上面的代码。我们保证,一旦你试图“忘记”类中state的行为,并以新的眼光看待这些代码,它就会有意义。

tip:方括号是什么意思?

你可能注意到声明变量时我们使用了方括号。

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

左边命名不是React的接口,你可以任意命名。

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

这种js语法叫做“数组解构赋值”。这会创建两个新的变量fruitsetFruit,这两个变量的值是hook返回的值的对应,fruit是第一个,setFruit是第二个。等价于下面:

  var fruitStateVariable = useState('banana'); // 返回一对值
  var fruit = fruitStateVariable[0]; // 第一个值
  var setFruit = fruitStateVariable[1]; // 第二个值

每次调用useState声明状态时,它都返回一个带有两个值的数组。第一个是当前状态值,第二个是更新函数。[0]和[1]访问它们有点令人困惑,因为它们具有特定的含义。因此我们用数组解构赋值替代。

注意
你可能很好奇React如何知道哪个组件useState对应,因为我们没有将这样的任何内容传递给React。详见答疑

tip:多个状态

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

function ExampleWithManyStates() {
// 多个状态
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
}  

上面的组件中,我们有age,fruit和todos作为本地状态,我们可以逐个更新他们:

function handleOrangeClick() {
setAge(40);
setFruit('orange');
}

你不必使用许多状态变量。状态变量可以很好地保存对象和数组,因此仍然可以将相关数据组合在一起。不同的是,类的状态更新是合并,而hook的状态更新是替换!

冀ICP备19028007号