React Hooks 05

React Hooks 05

useContext()和 useReducer()配合使用可以减少组件层级

useContext()

useContext()会创建一个上下文对象,对外暴露消费者和生产者,在上下文之内的所有子组件都可以访问这个上下文环境之内的数据

简单的说 context 就是对他所包含的组件树提供全局共享数据的技术

缺点:

  1. 增加调试复杂度,很难跟踪某个 context 的变化是如何产生的
  1. 让组件复用变得困难,因为一个组件使用 context,他必须确保被用到的地方必须有个 context 的 provider 在父组件上

代码:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import React, { useState, useContext } from "react";

// 创建一个上下文,提供两种不同的页面主题样式
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee",
},
dark: {
foreground: "#ffffff",
background: "#222222",
},
};
const ThemeContext = React.createContext(themes.light);

// ThemedButton做为消费者,通过useContext获取上下文
function ThemedButton(props) {
const theme = useContext(ThemeContext);
const [themes, setthemes] = useState(theme.dark);

return (
<div>
<div
style={{
width: "100px",
height: "100px",
background: themes.background,
color: themes.foreground,
}}
></div>
<button onClick={() => setthemes(theme.light)}>Light</button>
<button onClick={() => setthemes(theme.dark)}>Dark</button>
</div>
);
}

// 创建一个toolbar组件,里面包含了ThemedButton
// ThemeContext.Provider包裹,value就是提供的上下文对象
const ToolBar = () => {
return (
<ThemeContext.Provider value={themes}>
<ThemedButton />
</ThemeContext.Provider>
);
};

export default ToolBar;

useReducer()

工作流程:

image-20220801182429851

代码:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React, { useReducer } from "react";

const AddAndMinus = () => {
// 初始状态
const initState = {
count: 0,
};

// reducer根据action进行逻辑处理
// preState是老状态
// action是dispatch过来的
const reducer = (preState, action) => {
switch (action.type) {
case "add":
// 不可以直接对preState进行修改
return { count: preState.count + 1 };
case "minus":
return { count: preState.count - 1 };
default:
return preState;
}
};

// 订阅useReducer
const [state, dispatch] = useReducer(reducer, initState);

return (
<div>
<button
onClick={() => {
// dispatch出去
dispatch({
type: "add",
});
}}
>
+
</button>
{state.count}
<button
onClick={() => {
// dispatch出去
dispatch({
type: "minus",
});
}}
>
-
</button>
</div>
);
};

export default AddAndMinus;

特点:

  1. 代码变长,但理解起来更简洁明了,拥有更好的可读性
  2. reducer 可以将逻辑与 ui 分离
  3. state 都集中到 reducer 中进行处理,更容易复用 state 逻辑变化代码,特别对于 state 变化很复杂的场景
  4. 深层子组件需要修改一些状态,state 变化复杂,一个操作需要修改很多 state,ui 与业务分开维护,优先考虑使用 reducer