React入门笔记(五):Redux、react-redux
# 八、Redux
# 8.1、redux介绍
解决React数据管理(状态管理),用于中大型,数据比较庞大组件之间数据交互多的情况下使用。如果你不知道是否需要使用Redux,那么你就不需要用它!
- 解决组件的数据通信。
- 解决数据和交互较多的应用
热镀锌只是一种状态管理的解决方案!
- store:数据仓库,保存数据的地方
- state:是一个对象,数据仓库里的所有数据都放到一个state里
- action:一个动作,可以触发数据改变的方法
- dispatch:将动作触发成方法
- reducer:是一个函数,通过获取动作,改变数据,生成一个新的state,从而改变页面
# 8.2、安装redux
npm install redux --save
1
# 8.3、使用redux
初始化数据
//创建一个仓库
const store = createStore(reducer)
//用于通过action创建新的state
//reduce有2个作用,初始化数据、通过获取action改变数据
const reducer = function(state={num:0},action){
switch(action.type){
case "add":
state.num++;
break;
case "decrement":
state.num--;
break;
default:
break;
}
return {...state} //相当于对象的copy
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
获取数据
store.getState()
1
修改数据:通过action来修改数据
function add(){
//通过仓库的方法dispatch进行修改数据
store.dispatch({type:"add",content:{od:1,msg:'hello'}})
console.log(store.getState().num)
}
function decrement(){
//通过仓库的方法dispatch进行修改数据
store.dispatch({type:"decrement"})
console.log(store.getState().num)
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
修改视图:监听数据的变化,重新渲染内容
ReactDOM.render(<Counter/>,document.getElementById('root'))
store.subscribe(()=>{
ReactDOM.render(<Counter/>,document.getElementById('root'))
})
1
2
3
4
5
6
2
3
4
5
6
完整代码,计数器案例:
import React from "react";
import ReactDOM from "react-dom";
import {createStore} from 'redux';
//用于通过action创建新的state
const reducer = function(state={num:0},action){
switch(action.type){
case "add":
state.num++;
break;
case "decrement":
state.num--;
break;
default:
break;
}
return {...state} //相当于对象的copy
}
//创建一个仓库
const store = createStore(reducer)
console.log(store)
function add(){
//通过仓库的方法dispatch进行修改数据
store.dispatch({type:"add",content:{od:1,msg:'hello'}})
console.log(store.getState().num)
}
function decrement(){
//通过仓库的方法dispatch进行修改数据
store.dispatch({type:"decrement"})
console.log(store.getState().num)
}
//函数式计数器组件
const Counter = (props) =>{
return(
<div>
<h1>计数数量:{store.getState().num}</h1>
<button onClick={add}>计数+1</button>
<button onClick={decrement}>计数-1</button>
</div>
)
}
ReactDOM.render(<Counter/>,document.getElementById('root'))
store.subscribe(()=>{
ReactDOM.render(<Counter/>,document.getElementById('root'))
})
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
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
# 8.4、react-redux
安装:
npm install react-redux --save
1
概念:
Provider是一个组件:自动的将store里的state和我们的组件进行关联。
mapStateToProps:这个函数用于将store的state映射到组件的props里
mapDispatchToProps:将store中的dispatch映射到组件的props里,实现了方法的共享
connect方法:将组件和数据(方法)进行连接
使用:
初始化数据,实例化store:
const reducer = (state={num:0},action) =>{
switch(action.type){
case "add":
state.num++;
break;
default:
break;
}
return {...state}
}
const store = createStore(reducer)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
数据的获取,数据的修改
将state映射到组件的props里,将修改数据的方法映射到组件的props里
//将state映射到props函数
const mapStateToProps = (state) =>{
return {
value:state.num
}
}
//将修改state数据的方法映射到props
const mapDispatchToProps = (dispatch) =>{
return {
onAddClick:()=>dispatch(addAction)
}
}
//将上面的这两个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter)
class Counter extends React.Component{
render(){
//记录数,通过store的state传给props,直接通过props就可以将state的数据获取
const value = this.props.value;
//将修改数据的事件或方法传入到props
const onAddClick = this.props.onAddClick;
//等同于vuex的mapMutation mapState
return (
<div>
<h1>计数的数量:{value}</h1>
<button onClick={onAddClick}>数字+1</button>
</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
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
完整代码:
import React from "react";
import ReactDOM from "react-dom";
import {createStore} from 'redux'
import {Provider,connect} from 'react-redux'
class Counter extends React.Component{
render(){
//记录数,通过store的state传给props,直接通过props就可以将state的数据获取
const value = this.props.value;
//将修改数据的事件或方法传入到props
const onAddClick = this.props.onAddClick;
//等同于vuex的mapMutation mapState
return (
<div>
<h1>计数的数量:{value}</h1>
<button onClick={onAddClick}>数字+1</button>
</div>
)
}
}
const addAction = {
type:'add'
}
const reducer = (state={num:0},action) =>{
switch(action.type){
case "add":
state.num++;
break;
default:
break;
}
return {...state}
}
const store = createStore(reducer)
//将state映射到props函数
const mapStateToProps = (state) =>{
return {
value:state.num
}
}
//将修改state数据的方法映射到props
const mapDispatchToProps = (dispatch) =>{
return {
onAddClick:()=>dispatch(addAction)
}
}
//将上面的这两个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter)
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>
,document.getElementById('root')
)
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
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
再进行额外的扩展,将reducer扩展,实现多个状态的判断:
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";
class Counter extends React.Component {
render() {
//记录数,通过store的state传给props,直接通过props就可以将state的数据获取
const value = this.props.value;
//将修改数据的事件或方法传入到props
const onAddClick = this.props.onAddClick;
const onAddClick5 = this.props.onAddClick5;
//等同于vuex的mapMutation mapState
return (
<div>
<h1>计数的数量:{value}</h1>
<button onClick={onAddClick}>数字+1</button>
<button onClick={onAddClick5}>数字+5</button>
</div>
);
}
}
const addAction = {
type: "add",
};
const ActionFnObj = {
add: function (state, action) {
state.num++;
return state;
},
addNum: function (state, action) {
state.num = state.num + action.num;
return state;
},
};
const reducer = (state = { num: 0 }, action) => {
if (action.type.indexOf("redux") === -1) {
state = ActionFnObj[action.type](state, action);
return { ...state };
} else {
return state;
}
};
const store = createStore(reducer);
//将state映射到props函数
const mapStateToProps = (state) => {
return {
value: state.num,
};
};
//将修改state数据的方法映射到props
const mapDispatchToProps = (dispatch) => {
return {
onAddClick: () => dispatch(addAction),
onAddClick5: () => dispatch({ type: "addNum", num: 5 }),
};
};
//将上面的这两个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件
const App = connect(mapStateToProps, mapDispatchToProps)(Counter);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
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
75
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
75
编辑 (opens new window)
上次更新: 2022/08/26, 15:52:02