本文主要是介绍Redux记录:Store是如何自动调用reducers来处理action的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Redux记录:Store是如何自动调用reducers来处理action的
作为一个后端程序员,经常也要写一点前端、维护一下前端。因此一直在与前端打交道,但是一直没有理解当用户操作view通过dispatch发出 action之后,我们定义的一系列的reducer是如何来自动执行处理的。
先说结论:当用户操作view之后发出一个action,store会遍历所有的reducers来依次处理这个action来改变state。
今天浏览自己所在公司的官方博客,发现了这篇文章:Redux从设计到源码,仔细拜读了一下,收获很大,也解决了自己一直以来的困惑。
借此机会,自己也梳理一下。
在前端代码,自己经常看到类似如下的代码:
let store = createStore(reducers, undefined, compose(applyMiddleware(thunk,fetchMiddleware),window.devToolsExtension ? window.devToolsExtension() : f => f));
其中,reducers如下:
let reducers = combineReducers({AReducer, BReducer,CReducer});//AReducer等是我们自己定义的reducer
那么,当一个type=“A”的action产生后,是如何去这些{AReducer, BReducer,CReducer}来匹配查找然后进行处理的呢?自己当时的猜想是遍历所有的,看了源码之后原来真的是这样。
combineReducers
先看combineReducers的源码里面做了些什么,源码如下:
export default function combineReducers(reducers) {const reducerKeys = Object.keys(reducers)const finalReducers = {}for (let i = 0; i < reducerKeys.length; i++) {const key = reducerKeys[i]if (process.env.NODE_ENV !== 'production') {if (typeof reducers[key] === 'undefined') {warning(`No reducer provided for key "${key}"`)}}if (typeof reducers[key] === 'function') {finalReducers[key] = reducers[key]}}const finalReducerKeys = Object.keys(finalReducers)let unexpectedKeyCacheif (process.env.NODE_ENV !== 'production') {unexpectedKeyCache = {}}let shapeAssertionErrortry {assertReducerShape(finalReducers)} catch (e) {shapeAssertionError = e}//返回的是如下这个函数,用于处理actionreturn function combination(state = {}, action) {if (shapeAssertionError) {throw shapeAssertionError}if (process.env.NODE_ENV !== 'production') {const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache)if (warningMessage) {warning(warningMessage)}}let hasChanged = falseconst nextState = {}for (let i = 0; i < finalReducerKeys.length; i++) {const key = finalReducerKeys[i]const reducer = finalReducers[key]const previousStateForKey = state[key]const nextStateForKey = reducer(previousStateForKey, action)if (typeof nextStateForKey === 'undefined') {const errorMessage = getUndefinedStateErrorMessage(key, action)throw new Error(errorMessage)}nextState[key] = nextStateForKeyhasChanged = hasChanged || nextStateForKey !== previousStateForKey}return hasChanged ? nextState : state}}
上面的代码比较长,只需要注意两点即可:
1、将一系列的reducer以(reducerKey,reducer)存储在finalReducers中。
2、返回的函数将在store中自动调用,来处理action。至于如何处理的,下面分析完createStore之后将会分析。
createStore
下面是createStore方法的部分源码,由于store.dispatch(action)是用来分发action,这是修改state的唯一方式,基于此我们这里只关注dispatch方法,因此只对其进行了保留,如果想对其他方法有了解,可以参考博文:Redux从设计到源码,
export default function createStore(reducer, preloadedState, enhancer) {//省略类型检查 let currentReducer = reducerlet currentState = preloadedStatelet currentListeners = []let nextListeners = currentListenerslet isDispatching = false//省略其他方法,只保留了dispatch方法 function dispatch(action) {//省略了类型检查 try {isDispatching = truecurrentState = currentReducer(currentState, action) //分析} finally {isDispatching = false}const listeners = currentListeners = nextListenersfor (let i = 0; i < listeners.length; i++) {const listener = listeners[i]listener()}return action}}
store.dispatch()方法总结:
1、调用Reducer,传参(currentState,action)。
2、按顺序执行listener。
3、返回action。
下面分析第一点:调用Reducer,传参(currentState,action),即如下这行代码
currentState = currentReducer(currentState, action)
前面我们说过,currentReducer所指的就是由这行代码let reducers = combineReducers({AReducer, BReducer,CReducer});
所产生的reducers,这个reducers是如下这个函数:
function combination(state = {}, action) {//省略了部分检查代码let hasChanged = falseconst nextState = {}//对所有的reducers进行遍历来处理action。for (let i = 0; i < finalReducerKeys.length; i++) {const key = finalReducerKeys[i]const reducer = finalReducers[key]const previousStateForKey = state[key]//利用这个reducer来处理actionconst nextStateForKey = reducer(previousStateForKey, action)if (typeof nextStateForKey === 'undefined') {const errorMessage = getUndefinedStateErrorMessage(key, action)throw new Error(errorMessage)}//保存state并判断状态是否改变了。nextState[key] = nextStateForKeyhasChanged = hasChanged || nextStateForKey !== previousStateForKey}return hasChanged ? nextState : state}
上面比较简单哈,看完这里的源码是不是就理解了,当用户操作view产生一个action之后,store是如何自动调用reducers来处理action的哈。
这篇关于Redux记录:Store是如何自动调用reducers来处理action的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!