Description
本文博客地址: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.count
和 this.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>
在函数组件中,已经有了 setCount
和 count
变量,不需要再使用 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 语法称为“数组解构”。它的意思是创建两个新变量 fruit
和 setFruit
,其中 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' }]);
在上面的组件中,age
,fruit
和 todos
作为局部变量,可以单独更新它们:
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
。**它允许你在组件中执行副作用的操作,类似类组件中的生命周期方法。