# react-redux实现
其实 react-redux 主要就两个方法 Provider,connect
import React from 'react'
import PropTypes from 'prop-types'
//provider
export class Provider extends React.Component {
static childContextTypes = {
store: PropTypes.object.isRequired
}
getChildContext() {
return { store: this.store }
}
constructor(props, context) {
super(props, context)
this.store = props.store
}
render() {
return this.props.children
}
}
//connect
function bindActionCreator(actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(...args));
}
function bindActionCreators(actionCreator, dispatch) {
//actionCreators 可以是一个普通函数或者是一个对象
if (typeof actionCreator === 'function') {
//如果是函数,返回一个函数,调用时,dispatch 这个函数的返回值
bindActionCreator(actionCreator, dispatch);
} else if (typeof actionCreator === 'object') {
//如果是一个对象,那么对象的每一项都要都要返回 bindActionCreator
const boundActionCreators = {}
for (let key in actionCreator) {
boundActionCreators[key] = bindActionCreator(actionCreator[key], dispatch);
}
return boundActionCreators;
}
}
export const connect = (
mapStateToProps = state => ({}),
mapDispatchToProps = {}
) => (WrapComponent) => {
return class ConnectComponent extends React.Component {
static contextTypes = {
store: PropTypes.object
}
constructor(props, context) {
super(props, context)
this.state = {
props: {}
}
}
// 2 实现了mapStateToProps
componentDidMount() {
const { store } = this.context
this.unsub = store.subscribe(() => this.update())
this.update()
}
update() {
const { store } = this.context
// store.getState()这就是为什么mapStateToProps函数里面能拿到state
const stateProps = mapStateToProps(store.getState(), this.props)
// 方法不能直接给,因为需要dispatch
/**
function addGun() {
return { type: ADD_GUN }
}
直接执行addGun() 毫无意义
要 addGun = () => store.dispatch(addGun()) 才有意义,其实就是把actionCreator包了一层
bindActionCreators在手写redux api实现了
*/
const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch)
// 注意state的顺序问题会覆盖
//这里应该对比一下 props 是否发生变化
this.setState({
props: {
...this.state.props,
...stateProps,
...dispatchProps,
}
})
}
componentWillUnmount() {
//取消订阅
this.unsub();
}
// 1
render() {
return <WrapComponent {...this.state.props}></WrapComponent>
}
}
}
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# Provider
就是一个高阶组件,给整个项目添加了一个 store 的context
# connect
也是一个HOC,它拿到放在context上的store,然后订阅一个更新this.unsub = store.subscribe(() => this.update())
当执行更新时,把store.getState() 获取state,传给 传进来的WrapComponent组件
至此,react-redux 完成,下面看两个常用的 中间件
# logger
export const logger = store => next => action => {
if (typeof action !== 'function') {
console.log('dispatching', action)
}
let result = next(action)
console.log('next state', store.getState())
return result
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# redux-thunk
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => (next) => (action) => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
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