动手实现react-redux之五Provider终篇

现在代码中依赖 context 只有 Index 组件了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Index extends Component {
static childContextTypes = {
store: PropTypes.object
};

getChildContext() {
return { store };
}

render() {
return (
<div>
<Header />
<Content />
</div>
);
}
}

这里使用 context 的主要是为了将 store 放入 context 里面,方便子组件 connect 的时候可以拿得到 store。我们可以将这块的内容抽出来单独做个组件,并将需要使用 store 的组件作为这个组件的子组件。

这个组件命名为 Provider (提供者)。新增一个 src/Provider.js,代码如下:

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
import React from "react";
import PropTypes from "prop-types";

class Provider extends React.Component {
static childContextTypes = {
store: PropTypes.object.isRequired
};
static propTypes = {
store: PropTypes.object
};

getChildContext() {
return {
store: this.props.store
};
}


render() {

return (
<React.Fragment>
{this.props.children}
</React.Fragment>
);
}
}

export default Provider;

Provider 做的事情也很简单,它就是一个容器组件,会把嵌套的内容原封不动作为自己的子组件渲染出来。它还会把外界传给它的 props.store 放到 context,这样子组件 connect 的时候都可以获取到。

然后重构 src/index.js:

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
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Header from "./Header";
import Content from "./Content";
import "./index.css";
import Provider from "./Provider";

function createStore(reducer) {
let events = [];
let state = null;

let store = {
subscribe: (event) => events.push(event),
dispatch: (action) => {
state = reducer(state, action);
events.forEach((event) => event());
},
getState: () => state
};
// 初始化state
store.dispatch({});
return store;
}

function themeReducer(state, action) {
if (!state) {
return {
themeColor: "red"
};
}
switch (action.type) {
case "CHANGE_THEME_COLOR":
return { ...state, themeColor: action.themeColor };
default:
return state;
}
}

const store = createStore(themeReducer);


ReactDOM.render(
<Provider store={store}>
<Header />
<Content />
</Provider>,
document.getElementById("root")
);

这样我们就把所有关于 context 的代码从组件里面删除了。

现在通过这种方式大家不仅仅知道了 React-redux 的基础概念和用法,而且还知道这些概念到底是解决什么问题,为什么 React-redux 这么奇怪,为什么要 connect,为什么要 mapStateToProps 和 mapDispatchToProps,什么是 Provider,我们通过解决一个个问题就知道它们到底为什么要这么设计的了。

参考

http://huziketang.mangojuice.top/books/react/