react-hooks的正确认知
# react-hooks 的正确认知
# 实例带入
2x + 1 = y
1
看上述公式,其中 x 的变化会导致 y 的变化
- x: 自变量
- y: 因变量
# 对号入座
下面我们列举出常用的几个hooks进行对号入座
- useState
- useEffect
- useMemo
- useReducer
- useContext
- useCallBack
- useRef
上述几个hooks除了useRef,其余几个都可以归类与自变量和因变量
| 自变量 | 因变量 |
|---|---|
| useState | useEffect |
| useReducer | useMemo |
| useContext | useCallBack |
# useState
export default function App() {
const [count, setCount] = useState(0);
const handleChange = () => setCount(count + 1);
return (
<div>
<ul onClick={handleChange}>
<li>count是:{count}</li>
</ul>
</div>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14

export default function App() {
const [count, setCount] = useState(0);
const result = count * 2 + 1;
const handleChange = () => setCount(count + 1);
return (
<div>
<ul onClick={handleChange}>
<li>count是:{count}</li>
<li>result是: {result}</li>
</ul>
</div>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

自变量修改引起试图渲染 自变量变化引起因变量修改,因变量修改引起试图渲染
# useMemo和useCallBack
useMemo 在此处用来缓存一个因变量 useCallBack 在此处用来缓存一个函数类型的因变量
export default function App() {
const [count, setCount] = useState(0);
const result = useMemo(() => count * 2 + 1, [count]);
const handleChange = useCallback(() => setCount(count + 1), [count]);
return (
<div>
<ul onClick={handleChange}>
<li>count是:{count}</li>
<li>result是: {result}</li>
</ul>
</div>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用hooks显示的指明因变量有什么好处呢?
- 当使用的时候
result和handleChange会被缓存起来,只要count不变,它们始终读取的是缓存中的数据; - 不使用
useMemo和useCallBack是每次count改变的时候会创建新的result和新的handleChange;
这涉及到react的性能优化,当然也不是使用
useMemo和useCallBack越多越好,后续我们会继续学习什么时候使用useMemo和useCallBack比较好
# 副作用函数
组件的功能不仅局限于渲染视图,还能产生副作用;

纯函数:如果一个函数传入一个固定的输入一定会产生固定的输入,则此函数是纯函数
包含副作用函数:如果传入一固定的参数,不因有固定的输出,则说改函数是包含副作用的
1
2
3
2
3
在函数组件中可以通过useEffect来定义有副作用的因变量
假设我们count变化之后,让浏览器的title也改变; 改变标题就是副作用;

# useContext
接下来我们继续修改我们的例子
export default function App() {
const [count, setCount] = useState(0);
const result = useMemo(() => count * 2 + 1, [count]);
useEffect(() => {
document.title = count + '新标题';
}, [count]);
const handleChange = useCallback(() => setCount(count + 1), [count]);
const RenderCount = ({ data }) => {
return <i>{data}</i>;
};
return (
<div>
<ul onClick={handleChange}>
<li>
count是: <RenderCount data={count} />
</li>
<li>
result是: <RenderCount data={result} />
</li>
</ul>
</div>
);
}
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
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

如上图可以看出,一个字变量和因变量又能作为另一个组件(子组件)的自变量和因变量,使用我们上述方式如图中叶子节点视图组件拿到根节点的视图组件的参数需要逐一传递,很复杂;
此时就又了useContext,在第一级组件通过createContext创建Context后,其子组件及其子组件的字组件等都能通过useContext可以直接使用第一级组件通过creatContext创建的Context。
总结:通过这种方式使得跨层级的传递自变量变得很简单
# useRef
除了字变量和因变量外还有一种变量,他紧紧是其缓存数据作用,不会触发视图重新渲染
export default function App() {
const renderCountRef = useRef(1);
const isOdd = renderCountRef.current % 2 !== 0;
const [count, setCount] = useState(0);
useEffect(() => {
count && renderCountRef.current++;
}, [count]);
const result = count * 2 + 1;
const handleChange = () => setCount(count + 1);
const RenderCount = ({ data }) => {
return <i>{data}</i>;
};
return (
<div>
<ul onClick={handleChange}>
{isOdd && (
<li>
count是: <RenderCount data={count} />
</li>
)}
<li>
result是: <RenderCount data={result} />
</li>
</ul>
</div>
);
}
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
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

总结
useState:定义自变量
useMemo:定义无辅助作用的因变量
useCallBack:定义无辅助作用的因变量
useEffect:定义有辅助作用的因变量
useReducer:可以看作是进阶版的useState,他使用redux的理念,
将多个state合并成一个,本质上也是因变量
useContext:为了跨组件层级操作自变量
useRef:为了让组件逻辑更灵活
编辑 (opens new window)
上次更新: 2025/04/18, 01:42:12
