react之自定义react-redux的provider、connect

Provider

// Provider把store放到context里,所有的子元素可以直接取到store
import React from 'react'
import PropTypes from 'prop-types'
import {bindActionCreators} from './utils.js'

export const connect = (mapStateToProps=state=>state,mapDispatchToProps={})=>(WrapComponent)=>{
        return class ConnectComponent extends React.Component{
                static contextTypes = {
                        store:PropTypes.object
                }
                constructor(props, context){
                        super(props, context)
                        this.state = {
                                props:{}
                        }
                }
                componentDidMount(){
                        const {store} = this.context
                        store.subscribe(()=>this.update())
                        this.update()
                }
                update(){
                        const {store} = this.context
                        const stateProps = mapStateToProps(store.getState())
                        const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch)
                        this.setState({
                                props:{
                                        ...this.state.props,
                                        ...stateProps,
                                        ...dispatchProps        
                                }
                        })
                }
                render(){
                        return <WrapComponent {...this.state.props}></WrapComponent>
                }
        }
}

export class Provider extends React.Component{
        static childContextTypes = {
                store: PropTypes.object
        }
        getChildContext(){
                return {store:this.store}
        }
        constructor(props, context){
                super(props, context)
                this.store = props.store
        }
        render(){
                return this.props.children
        }
}


utils.js

export function createStore(reducer, enhancer){
        if (enhancer) {
                return enhancer(createStore)(reducer)
        }
        let currentState = {}
        let currentListeners = []

        function getState(){
                return currentState
        }
        function subscribe(listener){
                currentListeners.push(listener)
        }
        function dispatch(action){
                currentState = reducer(currentState, action)
                currentListeners.forEach(v=>v())
                return action
        }
        dispatch({type:'@IMOOC/WONIU-REDUX'})
        return { getState, subscribe, dispatch}
}

// 自定义applyMiddleware函数
export function applyMiddleware(...middlewares){
        return createStore=>(...args)=>{
                const store = createStore(...args)
                let dispatch = store.dispatch

                const midApi = {
                        getState:store.getState,
                        dispatch:(...args)=>dispatch(...args)
                }
                const middlewareChain = middlewares.map(middleware=>middleware(midApi))
                dispatch = compose(...middlewareChain)(store.dispatch)
                return {
                        ...store,
                        dispatch
                }

        }
}
// 自定义compose函数
export function compose(...funcs){
        if (funcs.length==0) {
                return arg=>arg
        }
        if (funcs.length==1) {
                return funcs[0]
        }
        return funcs.reduce((ret,item)=> (...args)=>ret(item(...args)))
}
function bindActionCreator(creator, dispatch){
        return (...args) => dispatch(creator(...args))
}
export function bindActionCreators(creators,dispatch){
        return Object.keys(creators).reduce((ret,item)=>{
                ret[item] = bindActionCreator(creators[item],dispatch)
                return ret
        },{})
}