在大型項(xiàng)目中將代碼拆分為多個(gè)按需加載的js包荷科,redux中也可以實(shí)現(xiàn)動(dòng)態(tài)添加reducer到store,可以使用replaceReducer
:
該函數(shù)使用新的 root reducer
替代當(dāng)前活動(dòng)的 root reducer
纱注。調(diào)用該函數(shù)將替換內(nèi)部 reducer 的引用畏浆,并 dispatch
一個(gè) action
以初始化新加入的 reducer
:
const newRootReducer = combineReducers({
existingSlice: existingSliceReducer,
newSlice: newSliceReducer
})
store.replaceReducer(newRootReducer)
我們可能想從應(yīng)用程序的任何地方調(diào)用 store.replaceReducer()
。因此狞贱,它使我們可以很輕易的定義一個(gè)可重用的 injectReducer()
函數(shù)刻获。該函數(shù)能夠保持對(duì)所有現(xiàn)有 slice reducer
的引用,并可將新 reducer
附加到 store
實(shí)例瞎嬉。
下面是injectReducer
使用的兩種方法蝎毡,路過(guò)的大佬可以幫忙對(duì)比一下兩種方案:
import { createStore } from 'redux'
// 定義將始終存在于應(yīng)用程序中的 Reducer
const staticReducers = {
users: usersReducer,
posts: postsReducer
}
// Configure the store
export default function configureStore(initialState) {
const store = createStore(createReducer(), initialState)
// 添加一個(gè)對(duì)象以跟蹤已注冊(cè)的異步 Reducer
store.asyncReducers = {}
//創(chuàng)建注入 reducer 函數(shù)
// 此函數(shù)添加 async reducer厚柳,并創(chuàng)建一個(gè)新的組合 reducer
store.injectReducer = (key, asyncReducer) => {
store.asyncReducers[key] = asyncReducer
store.replaceReducer(createReducer(this.asyncReducers))
}
// 返回修改后的 store
return store
}
function createReducer(asyncReducers) {
return combineReducers({
...staticReducers,
...asyncReducers
})
}
現(xiàn)在,只需要調(diào)用 store.injectReducer 函數(shù)即可向 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),
};
}
關(guān)于Reflect和hoist-non-react-statics的具體用法可以參考鏈接别垮。