前文介绍了如下的Hooks例子 https://blog.csdn.net/qq_39606853/article/details/122283215?spm=1001.2014.3001.5501
import React, { useState } from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
我们将通过将这段代码与一个等价的 class 示例进行比较来开始学习 Hook。
Class的例子
如果使用class组件,以下的代码会看起来比较熟悉
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增加1。
Hooks和function组件
提醒一下,React里的function组件是这么写的
const Example = (props) => {
// 你可以在这使用 Hook
return <div />;
}
或是这样:
function Example(props) {
// 你可以在这使用 Hook
return <div />;
}
你之前可能就知道了这些都是无状态的组件。我们现在引入在这些组件里增加state的能力,所以我们更喜欢叫它function组件。
Hooks不能在class组件内部工作。但是你可以使用它替代class组件。
什么是Hooks
在我们新的例子首先导入useState
import React, { useState } from 'react';
function Example() {
// ...
}
什么是一个Hook?一个Hook就是一个特殊的方法可能让你"勾入"React的特性里。比如,useState是一个Hook用来让你在function组件里增加React的state。之后我们将会学习一些其他的Hooks。
什么时候使用Hook?如果你想写一个function组件并在其中增加一些state,之前你只能把它改为class组件的形式,现在你可以在function组件里用Hook来实现增加state的功能。现在让我们开始实现它。
声明一个State变量
在一个class组件里,我们通过在构造函数里传入{ count: 0 }给this.setState( )把count设为0。
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() {
// 声明一个叫 “count” 的 state 变量
const [count, setCount] = useState(0);
调用useState是干了啥?它声明了一个state变量。这个变量叫count,我们也可以命名成任意别的名字,比如banana。这是一种在方法调用之间保存值的方法——useState是一个新的完全可以用来替代class组件里的this.state的方式。一般来说,变量在方法调用结束后消失,但state变量能被React保存住。
我们给useState传递什么参数?useState( )唯一的参数就是初始状态。不像在class组件里,状态不是必须为一个对象。我们可以设为一个数字或者字符串都可以。在例子中,我们仅仅期望当用户点击后反映出一个数字来,所以传递0给初始状态(如果我们想要两个不同的state变量,可以调用useState两次)。
useState返回什么?它返回了一对值——当前的状态和更新状态的方法。这就是我们写const [count, setCount] = useState()的原因。和class组件里的this.state.count以及this.setState是类似的,除了你是一下子获得它们俩的。
现在我们知道了useState干了啥,我们的例子就变得更有意思了
import React, { useState } from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量
const [count, setCount] = useState(0);
我们声明了一个count状态变量,把它设为0。React将会在重复渲染中记住它,并把最新的值返回给我们的方法。如果我们想更新它,我们可以调用setCount。
读取状态
当我们想要在class组件显示当前计数值的时候,我们读取this.state.count
<p>You clicked {this.state.count} times</p>
在函数中,我们可以直接用 count:
<p>You clicked {count} times</p>
更新状态
在class组件里,我们通过调用this.setState( )来更新state。
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
在函数中,我们已经有了 setCount 和 count 变量,所以我们不需要 this:
<button onClick={() => setCount(count + 1)}>
Click me
</button>
总结
现在让我们来仔细回顾一下学到的知识,看下我们是否真正理解了。
import React, { 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。它可以让我们在function组件里保持住内部state。
-
第4行:在Example组件内部,我们通过调用useState声明了一个新的state变量。它返回了一对值。count反映了按钮点击的次数。我们传递给useState唯一参数就是state的初始值。第二个返回的是更新state的方法,命名为setState。
-
第9行:当用户点击时,我们调用setCount传递给一个新的值。React将会重新渲染Example组件,把新的count值传递给它。
好像很多的内容。别急!如果你发现你迷失了,再从上往下看一眼上面的代码。一旦你尝试忘掉class组件里的state用法并用新鲜的眼光扫视这些代码,你会发现很有趣。
提示:方括号有什么用?
你可能注意到我们用方括号定义了一个 state 变量
const [count, setCount] = useState(0);
等号左边名字并不是 React API 的部分,你可以自己取名字:
const [fruit, setFruit] = useState('banana');
这种 JavaScript 语法叫数组解构。它意味着我们同时创建了 fruit 和 setFruit 两个变量,fruit 的值为 useState 返回的第一个值,setFruit 是返回的第二个值。它等价于下面的代码:
var fruitStateVariable = useState('banana'); // 返回一个有两个元素的数组
var fruit = fruitStateVariable[0]; // 数组里的第一个值
var setFruit = fruitStateVariable[1]; // 数组里的第二个值
当我们使用 useState 定义 state 变量时候,它返回一个有两个值的数组。第一个值是当前的 state,第二个值是更新 state 的函数。使用 [0] 和 [1] 来访问有点令人困惑,因为它们有特定的含义。这就是我们使用数组解构的原因。
提示:使用多个 state 变量
将 state 变量声明为一对 [something, setSomething] 也很方便,因为如果我们想使用多个 state 变量,它允许我们给不同的 state 变量取不同的名称:
function ExampleWithManyStates() {
// 声明多个 state 变量
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
在上面的组件里,我们有age、fruit、todos这些state,我们可以单独的来更新它们。
function handleOrangeClick() {
// 和 this.setState({ fruit: 'orange' }) 类似
setFruit('orange');
}
不是非用多个state变量不可的。State变量可以为一个对象或者数组,这样你可以把相关的内容组织好。但是不像class组件里的this.setState,更新一个state变量永远只会更新它而不是合并它。