useState 可以说是目前最常用的Hook之一了。

简单使用

来看 useState 的简单用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const App = () => {
const [count, setCount] = React.useState(0);

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

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

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

用法总结如下:

  • useState(initial) 接收一个初始值作为参数。
  • 返回一个数组:count and setCount

count 保存state状态,默认有一个初始值;setCount 用于修改 count,每调用一次 setCount , 组件就取最新的 count 来重新渲染组件。

异步状态更新

如果状态的变更依赖之前的状态,上述的写法存在一些问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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>
);
};

每次单击按钮,都会延迟1秒执行setCount函数。但是如果一秒内多次点击按钮,状态值count不会发生变化。

为了解决这个问题,useState可以传入状态更新函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;

在setCount函数执行传入count, 确保是对最新的count进行操作。

结论:如果状态更新依赖于以前的状态,需要useState的更新函数中传入一个回调函数。