9.2.2 增强器实例reset
您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!
9.2.2 增强器实例reset
在实际的Redux应用中,有这样一个场景,一个页面已经完成了初始化,Redux Store已经创建完毕,甚至用户都已经做了一些交互动作。这时候页面要在不刷新的情况下切入另一个界面,这个界面拥有全新的功能模块,也就是说有全新的reducer、action构造函数和React组件。但是我们还想保持原有的Store对象,因为网页并没有刷新,一个应用本来就应该只有一个Store对象。
对于action构造函数和React组件好说,按照我们前面模块化的思想,React组件尽量不存储状态,状态都存在Redux Store上,action构造函数也直接替换就行,所以这个替换功能模块的问题根本上就是替换reducer和Redux Store上状态的问题。
Redux的store上有一个replaceReducer函数,可以帮助我们完成替换reducer的工作,但是store只有getState,可并没有replaceState。Redux这样设计就是杜绝对state的直接修改,我们都知道改变一个Redux Store状态的只能通过reducer,而驱动reducer就要派发一个action对象。
一个应用可能包含很多功能模块,即使每个模块都提供了修改属于自己store状态的action对象,那么这个替换过程也要给所有功能模块派发一个action对象,这样既复杂又不通用,无法实现。
所以,我们创造一个增强器,给创造出来的store对象一个新的函数reset,通过这一个函数就完成替换reducer和状态的功能,代码如下:
const RESET_ACTION_TYPE = '@@RESET';
const resetReducerCreator = (reducer, resetState) => (state, action) => {
if (action.type === RESET_ACTION_TYPE) {
return resetState;
} else {
return reducer(state, action);
}
};
const reset = (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer);
const reset = (resetReducer, resetState) => {
const newReducer = resetReducerCreator(resetReducer, resetState);
store.replaceReducer(newReducer);
store.dispatch({type: RESET_ACTION_TYPE, state: resetState});
};
return {
...store,
reset
};
};
export default reset;
即使是Store Enhancer,也无法打破Redux内在的一些限制,比如对state,增强器也不可能直接去修改state的值,依然只能通过派发一个action对象去完成。在这里定义一个特殊的action类型RESET_ACTION_TYPE,表示要重置整个store上的值,为了能够处理这个action类型,我们也要在reducer上做一些定制。
在reset函数中,先通过replaceReducer函数替换store原有的reducer,然后通过store的dispatch函数派发一个type为RESET_ACTION_TYPE的action对象。这个action对象可没有预期让任何应用的功能模块捕获到,完全是这个增强器自己消耗。
通过replaceReducer替换的新reducer在所有功能模块reducer之前被执行,所有通过了中间件管道的action对象先被resetReducerCreator函数的返回函数处理。在这个函数中,如果发现action对象的type为RESET_ACTION_TYPE,那就直接返回resetState作为整个Store的新状态,其他的action对象则交给其他reducer来处理。 深入浅出React和Redux