// react-redux.js import React from 'react'; import propTypes from 'prop-types'; export class Provider extends React.Component{ // 设置 childContext 状态值类型 static childContextTypes = { store: propTypes.object }; // 设置 childContext getChildContext(){ return {store: this.props.store} } render(){ return this.props.children; } }
重写 App.js: 对 Provider 组件的调用// App.js import React, { Component } from 'react'; import { createStore } from './Demo/redux'; import { Provider } from './Demo/react-redux'; import { reducer } from './Demo/reducer'; import Demo from './Demo/Demo'; // 创建 store const store = createStore(reducer); class App extends Component { render() { // 调用接口 Provider return <Provider store={store}><Demo /></Provider>; } } export default App;
三、 react-redux API connect 高阶组件的实现
上文中在后代组件如果需要获取 store 则需要手动通过获取 react context 来调用 store 并且需要显性的调用 store 内部的方法来进行一些操作;接下来我们来实现这么一个高阶组件 connect,我们只需要提供所需的 redux state 以及 action 创建函数,即可通过 props 获取到相应的 redux state , 并且允许直接通过 props 调用action 创建函数来试图修改 redux state ;
创建高阶组件 connect// react-redux.js export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class NewComponent extends React.Component{ render(){ return <Component /> } } }
获取store// react-redux.js export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class NewComponent extends React.Component{ // 设置 context 状态值类型 static contextType = { store: propTypes.object }; // [1]获取 store [2]设置空 react state constructor(props, context){ super(props, context); this.store = context.store; this.state = {}; } render(){ return <Component /> } } }
添加监听对象,并尝试通过 props 将状态传递给子组件export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class NewComponent extends React.Component{ static contextType = { store: propTypes.object }; constructor(props, context){ super(props, context); this.store = context.store; this.state = {}; } // [1]添加监听对象 [2]手动执行监听对象,初始化 react state componentDidMount(){ this.store.subscribe(this.update); this.update(); } update = () => { // 获取全部redux state 并添加到 react state const state = this.store.getState(); this.setState(state); } render(){ // 通过 props 将 react state 全部传给子组件 return <Component {...this.state} /> } } }
通过 mapStateToProps 获取指定 redux state// react-redux.js export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class NewComponent extends React.Component{ static contextType = { store: propTypes.object }; constructor(props, context){ super(props, context); this.store = context.store; this.state = {}; } componentDidMount(){ this.store.subscribe(this.update); this.update(); } update = () => { // 执行 mapStateToProps 只获取用户指定需求的 state const state = this.store.getState(); const filterState = mapStateToProps(state); this.setState(filterState); } render(){ return <Component {...this.state} /> } } }
通过 mapDispatchToProps 获取 action 创建函数: 使用 dispatch 包裹后返回// react-redux.js // react-redux.js export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class NewComponent extends React.Component{ static contextTypes = { store: propTypes.object }; constructor(props, context){ super(props, context); this.store = context.store; this.state = {}; } componentDidMount(){ this.store.subscribe(this.update); this.update(); } update = () => { // 处理 state ===> 获取用户指定的 state const state = this.store.getState(); const filterState = mapStateToProps(state); // 使用 dispatch 对 mapDispatchToProps 中的 action 创建函数进行包裹后返回 const actionFun = {}; for(let key in mapDispatchToProps){ actionFun[key] = (...args) => { this.store.dispatch(mapDispatchToProps[key](...args)); } } // 一种简写方式: 骚操作 // const actionFun = Object.keys(mapDispatchToProps) // .reduce((total, item) => { // return { ...total, [item]: (...args) => {dispatch(mapDispatchToProps[item](...args));} // } } ,{}); this.setState({...filterState, ...actionFun}); } render(){ return <Component {...this.state} /> } } }
调用高阶组件:修改 Demo.jsx