美文网首页
reducer 动态注入

reducer 动态注入

作者: Mr君 | 来源:发表于2019-09-30 16:43 被阅读0次

    在大型项目中将代码拆分为多个按需加载的js包,redux中也可以实现动态添加reducer到store,可以使用replaceReducer
    该函数使用新的 root reducer 替代当前活动的 root reducer。调用该函数将替换内部 reducer 的引用,并 dispatch 一个 action 以初始化新加入的 reducer

    const newRootReducer = combineReducers({
      existingSlice: existingSliceReducer,
      newSlice: newSliceReducer
    })
    
    store.replaceReducer(newRootReducer)
    

    我们可能想从应用程序的任何地方调用 store.replaceReducer()。因此,它使我们可以很轻易的定义一个可重用的 injectReducer() 函数。该函数能够保持对所有现有 slice reducer 的引用,并可将新 reducer 附加到 store 实例。
    下面是injectReducer使用的两种方法,路过的大佬可以帮忙对比一下两种方案:

    import { createStore } from 'redux'
    
    // 定义将始终存在于应用程序中的 Reducer
    const staticReducers = {
      users: usersReducer,
      posts: postsReducer
    }
    
    // Configure the store
    export default function configureStore(initialState) {
      const store = createStore(createReducer(), initialState)
    
      // 添加一个对象以跟踪已注册的异步 Reducer
      store.asyncReducers = {}
    
      //创建注入 reducer 函数
      // 此函数添加 async reducer,并创建一个新的组合 reducer
      store.injectReducer = (key, asyncReducer) => {
        store.asyncReducers[key] = asyncReducer
        store.replaceReducer(createReducer(this.asyncReducers))
      }
    
      // 返回修改后的 store
      return store
    }
    
    function createReducer(asyncReducers) {
      return combineReducers({
        ...staticReducers,
        ...asyncReducers
      })
    }
    

    现在,只需要调用 store.injectReducer 函数即可向 store 添加新的 reducer。

    import React from 'react';
    import _ from 'lodash';
    import PropTypes from 'prop-types';
    import hoistNonReactStatics from 'hoist-non-react-statics';
    
    import getInjectors from './reducerInjectors';
    
    /**
     * Dynamically injects a reducer
     *
     * @param {string} key A key of the reducer
     * @param {function} reducer A reducer that will be injected
     *
     */
    export default ({ key, reducer }) => (WrappedComponent) => {
      class ReducerInjector extends React.Component {
        static WrappedComponent = WrappedComponent;
    
        static contextTypes = {
          store: PropTypes.object.isRequired,
        };
    
        static displayName = `withReducer(${WrappedComponent.displayName ||
          WrappedComponent.name ||
          'Component'})`;
    
        injectors = getInjectors(_.get(this.context, 'store'));
    
        componentWillMount() {
          const { injectReducer } = this.injectors;
          injectReducer(key, reducer);
        }
    
        render() {
          return <WrappedComponent {...this.props} />;
        }
      }
    
      return hoistNonReactStatics(ReducerInjector, WrappedComponent);
    };
    

    reducerInjectors.js

    import createReducer from 'js/redux/reducers';
    
    export function injectReducerFactory(store) {
      return function injectReducer(key, reducer) {
        // Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different
        if (
          Reflect.has(store.injectedReducers, key) &&
          store.injectedReducers[key] === reducer
        ) {
          return;
        }
    
        store.injectedReducers[key] = reducer; // eslint-disable-line no-param-reassign
        store.replaceReducer(createReducer(store.injectedReducers));
      };
    }
    
    export default function getInjectors(store) {
      return {
        injectReducer: injectReducerFactory(store),
      };
    }
    

    关于Reflect和hoist-non-react-statics的具体用法可以参考链接。

    相关文章

      网友评论

          本文标题:reducer 动态注入

          本文链接:https://www.haomeiwen.com/subject/kifwectx.html