React之Redux的基本使用
在项目中有这样的使用场景,就是多个组件需要共享同一个状态,或者其他组件想要更改某个组件里的状态,如果用组件传值跟消息发布 - 订阅虽然也能实现,但是实现起来却很繁琐,因此这时候就需要使用到 Redux 了,它是一个状态管理容器,帮助我们集中管理状态。
Redux 三要素:
- actions:js 普通对象,必须含有一个字符串类型的 type 字段表示将要执行的动作。
- store:维持应用的 state,提供 getState () 方法获取 state;通过 dispatch (action) 更新 state,通过 subscribe (listener) 注册监听器,通过 subscribe (listener) 返回的函数注销监听器。Redux 应用只有一个单一的 store
- reducers:纯函数,接收先前的 state 和 action,并返回新的 state
原理图:
现在就用一个加减运算的案例来说明 redux 如何使用。
# redux 使用
# 1、安装 Redux
npm install redux
1
# 2、编写 store 和 reducer 文件
在项目根目录的 src 文件夹下创建 redux 文件夹,在该文件夹下创建 store.js 文件和 countReducer.js 文件
// src/redux/countReducer.js
const initialState = 0
const countReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD':
return state + 1
case 'MINUS':
return state - 1
default:
return state
}
}
export default countReducer
// src/redux/store.js
import { createStore } from "redux"
import countReducer from "./countReducer";
export default createStore(countReducer)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 3、创建组件 Count.jsx
// class组件实现
import React, { Component } from 'react';
import store from "../../redux/store";
class Count extends Component {
state = {
count: store.getState()
}
// 加运算
handleAdd = () => {
store.dispatch({type: "ADD"})
}
// 减运算
handleReduce = () => {
store.dispatch({type: "MINUS"})
}
// 组件挂载时,监听store改变时,更新状态
componentDidMount() {
this.storeSubscribe = store.subscribe(() => {
this.setState({
count: store.getState()
})
})
}
// 组件卸载时取消监听
componentWillUnmount() {
this.storeSubscribe()
}
render() {
return (
<div>
<h3>当前结果:{this.state.count}</h3>
<button onClick={ () => this.handleAdd() }>加1</button>
<button onClick={ () => this.handleReduce() }>减1</button>
</div>
);
}
}
export default Count;
// function组件实现
import React, { useState, useEffect } from 'react';
import store from "../../redux/store";
const Count = () => {
const [count, setCount] = useState(store.getState());
useEffect(() => {
const unsubscribe = store.subscribe(() => {
setCount(store.getState())
})
return () => {
unsubscribe()
}
}, [count])
const handleAdd = () => {
store.dispatch({type: "ADD"})
}
const handleReduce = () => {
store.dispatch({type: "MINUS"})
}
return (
<div>
<h3>当前结果:{count}</h3>
<button onClick={ () => handleAdd() }>加1</button>
<button onClick={ () => handleReduce() }>减1</button>
</div>
);
};
export default 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
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
当应用越来越复杂时,我们可以将 reducer 函数拆分成多个单独的函数,拆分后的函数负责独立管理 state 的一部分,这里需要用到 combineReducers 辅助函数,它的作用是把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法。
例如,现在还有一个管理用户信息的 reducer,
const initialState = {
name: "张三",
age: 28
}
const userReducer = (state = initialState, action) => {
switch (action.type) {
case "changeAge":
return {
...state,
age: action.payload
}
default:
return state
}
}
export default userReducer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
那么 src/redux/store.js 文件则更改如下:
import { createStore, combineReducers } from "redux"
import countReducer from "./countReducer";
import userReducer from "./userReducer";
const reducer = combineReducers({
countReducer,
userReducer
})
export default createStore(reducer)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
此时,在 Count.jsx 组件中使用如下:
import React, {useState, useEffect} from 'react';
import store from "../../redux/store";
const Count = () => {
const [count, setCount] = useState(store.getState().countReducer);
const [user, setUser] = useState(store.getState().userReducer);
useEffect(() => {
const unsubscribe = store.subscribe(() => {
setCount(store.getState().countReducer)
setUser(store.getState().userReducer)
})
return () => {
unsubscribe()
}
}, [count, user])
const handleAdd = () => {
store.dispatch({type: "ADD"})
}
const handleReduce = () => {
store.dispatch({type: "MINUS"})
}
const changeAge = () => {
store.dispatch({type: "changeAge", payload: 100})
}
return (
<div>
<h3>当前结果:{count}</h3>
<h3>用户信息:姓名:{user.name},年龄:{user.age}</h3>
<button onClick={ () => handleAdd() }>加1</button>
<button onClick={ () => handleReduce() }>减1</button>
<button onClick={ () => changeAge() }>更改年龄</button>
</div>
);
};
export default 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
27
28
29
30
31
32
33
34
35
36
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
编辑 (opens new window)
上次更新: 7/1/2024, 4:56:33 PM