|
@@ -712,10 +712,114 @@ function TestUseState() {
|
|
}
|
|
}
|
|
```
|
|
```
|
|
|
|
|
|
|
|
+另外,所有状态变量的修改函数 在修改状态时可能是异步的。因此在修改函数中 直接获取状态 用作上一次状态的值 可能是错误的
|
|
|
|
|
|
|
|
+```jsx
|
|
|
|
+import { useState } from 'react';
|
|
|
|
+
|
|
|
|
+export default function Counter() {
|
|
|
|
+ let [count, setCount] = useState(0);
|
|
|
|
+
|
|
|
|
+ function addOne() {
|
|
|
|
+ setCount(count + 1);
|
|
|
|
+ }
|
|
|
|
+ function reduceOne() {
|
|
|
|
+ setCount(count - 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ <div>
|
|
|
|
+ <h3>计数器</h3>
|
|
|
|
+ <p>值为:{count}</p>
|
|
|
|
+ <p>
|
|
|
|
+ <button onClick={addOne}>+</button>
|
|
|
|
+ <button onClick={reduceOne}>-</button>
|
|
|
|
+ <button
|
|
|
|
+ onClick={() => {
|
|
|
|
+ // setCount 这些修改函数 可能是异步的。
|
|
|
|
+ // 因此下面代码不能将count设置为 3
|
|
|
|
+ setCount(count + 1);
|
|
|
|
+ setCount(count + 1);
|
|
|
|
+ setCount(count + 1);
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ +3
|
|
|
|
+ </button>
|
|
|
|
+ </p>
|
|
|
|
+ </div>
|
|
|
|
+ );
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+上面 +3 按钮会失效。因此在连续调用setCount时参数count每一次都是0,也就是说 你调用三次`setCount(1)`。
|
|
|
|
+
|
|
|
|
+为了 能够在异步更新状态时准确获取到上一次状态,可以给所有修改函数传入一个 函数类型值,它可以接收两个参数:上一个状态值preState,以及组件属性props,然后该函数返回新状态。
|
|
|
|
+
|
|
|
|
+上面代码中,将setCount调用方式改为如下即可:
|
|
|
|
+
|
|
|
|
+```jsx
|
|
|
|
+setCount((preCount) => preCount + 1);
|
|
|
|
+setCount((preCount) => preCount + 1);
|
|
|
|
+setCount((preCount) => preCount + 1);
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+**小结**
|
|
|
|
+
|
|
|
|
+1. hook函数必须在函数组件中使用
|
|
|
|
+2. hook函数必须组件顶层中调用,不能在其他语句中使用
|
|
|
|
+3. useState中返回的修改函数 可能是异步修改状态
|
|
|
|
|
|
### 8.2 useEffect
|
|
### 8.2 useEffect
|
|
|
|
|
|
|
|
+> Effect 译为 『副作用』。
|
|
|
|
+>
|
|
|
|
+> useEffect hook 就是在函数组件中执行副作用(和渲染无关)。
|
|
|
|
+>
|
|
|
|
+> useEffect是一个React Hook,可以让你将一个组件与外部系统同步。
|
|
|
|
+>
|
|
|
|
+> 其本质,就是用来实现一些生命周期的钩子。
|
|
|
|
+
|
|
|
|
+那么,useEffect 能帮助开发者实现那些生命周期钩子的效果呢?
|
|
|
|
+
|
|
|
|
+1. 每一次组件渲染时,都希望执行一些副作用
|
|
|
|
+
|
|
|
|
+ ```jsx
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ // 编写一些副作用代码。注意: 别随意修改状态
|
|
|
|
+ // 组件每次渲染 都会执行
|
|
|
|
+ })
|
|
|
|
+ ```
|
|
|
|
+
|
|
|
|
+2. 仅当组件首次渲染后执行一些副作用
|
|
|
|
+
|
|
|
|
+ ```jsx
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ // 仅会在组件首次渲染后执行一次,可以在这里发送http请求
|
|
|
|
+ // 模拟的就是componentDidMount钩子
|
|
|
|
+ console.log('===组件渲染后===');
|
|
|
|
+ }, []);
|
|
|
|
+ ```
|
|
|
|
+
|
|
|
|
+3. 在组件卸载前执行一些副作用
|
|
|
|
+
|
|
|
|
+ ```jsx
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ // 返回一个回调函数
|
|
|
|
+ return () => {
|
|
|
|
+ // 这里返回的回调 会在组件卸载前执行
|
|
|
|
+ // 可以在这里清除一些『垃圾』
|
|
|
|
+ console.log('MsgItem卸载了');
|
|
|
|
+ };
|
|
|
|
+ }, []);
|
|
|
|
+ ```
|
|
|
|
+
|
|
|
|
+4. 监听state或者props,只要有一发生变化就会执行一些副作用
|
|
|
|
+
|
|
|
|
+ ```jsx
|
|
|
|
+ ```
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
### 8.3 useMemo
|
|
### 8.3 useMemo
|
|
|
|
|
|
### 8.4 useCallback
|
|
### 8.4 useCallback
|