// 聚合函数 用于applymiddleware function compose(...funs) { const len = funs.length; if(len === 0) return a => a if(len === 1) return funs[0] return funs.reduce((left, right) => { return (...args) => right(left(...args)) }) } // store 原理 // 返回一个具有 createStore dispatch subscribe方法的对象 // redux 暴露的createStore 方法 const createStore = (reducer, enhancer) => { // enhancer 是一个增强器 比如中间件 applymiddleware if(enhancer) return enhancer(createStore)(reducer) let cur = undefined; let curlist = []; //存放监听函数 function getState() { return cur } function dispatch(action) { cur = reducer(cur, action) curlist.map(cl => cl()) } function subscribe(listener) { curlist.push(listener) } dispatch({type:'1111'}) ;//默认状态下 要先触发一次 return { getState, dispatch, subscribe } } // redux 暴露的 applymiddleware方法 // createStore(reducer, applymiddleware(logger, thunk)) // 起初list 是按照从做向右的方向执行 // 最后的执行结果是右向左执行 const applymiddleware = (...list) => { // 接受createStore作为参数 返回一个函数 return createStore => (...args) => { let store = createStore(...args); const midApi = { getState: store.getState, dispatch: store.dispatch } const chain = list.map( mw => mw(midApi)) // mw(midApi) 返回一个函数 const dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } } const logger = () => { return dispatch => action => { return dispatch(action) } } const thunk = () => { return dispatch =>action => { if(typeof action === 'function') action() dispatch(action) } }
// react-redux 提供provider connect方法 // provider 基于context原理 // connect 将dispatch state映射到props 并订阅变化用于实时刷新 import { connect } from "react-redux"; import { useContext, useState, useEffect } from "react"; const Context = React.createContext(); export const Provider = props => { return <Context.Provider value={props.store}> {props.children} </Context.Provider> } export const connect = ( mapStatetoProps = state => state, mapDispatchtoProps = {} // 爱react-redux 中 这个既可以是对象 可以是一个函数 ) => { return Cmp => { return () => { const store = useContext(Context) const getProps = () => { const stateProps = mapStatetoProps(store.getState()) const dispatchProps = bindActionCreators(mapDispatchtoProps, store.dispatch) } return { ...stateProps, ...dispatchProps } const [props, setProps] = useState({...getProps()}) useEffect(() => { store.subsribe(() => { setProps({...props, ...getProps()}) }) return store.unsubscribe() }, []) return <Cmp {...props}/> } } } function bindActionCreators(creators, dispatch) { return Object.keys(creators).reduceRight((ret, item) => { ret[item] = bindActionCreator(creator[item], dispatch) return ret }) } function bindActionCreator(creators, dispatch) { return (...args)=> dispatch(creators(...args)) }