摘要:歡迎關注源碼分析系列文章源碼分析之一源碼分析之二源碼分析之三源碼分析之四源碼分析之五文件對外暴露了一個函數,函數是的一個輔助性的函數,用于拆分里面的第一個參數函數。函數的返回值是一個函數,該函數是組合之后的一個標準的函數。
歡迎關注redux源碼分析系列文章:
redux源碼分析之一:createStore.js
redux源碼分析之二:combineReducers.js
redux源碼分析之三:bindActionCreators.js
redux源碼分析之四:compose.js
redux源碼分析之五:applyMiddleware
combineReducers.js文件對外暴露了一個函數combineReducers,combineReducer函數是redux的一個輔助性的函數,用于拆分createStore里面的第一個參數:reducer函數。combineReducer函數的返回值是一個函數,該函數是組合之后的一個標準的reducer函數。
一、分析combineReducers函數的參數:combineReducers函數僅包含一個參數reducers,reducers是一個object類型參數,比如:
let reducers = { users: function getUsersReducer(){}, userInfo: function getUserInfoReducer(){} }二、分析combineReducers返回之前做了什么:
1、從傳入的參數里面提取出合法的reducers(reducers的每一個key對應的value值是函數,才是合法的子reducer),賦值給新的局部變量:finalReducers
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}"`) } } //過濾出reducers對應的value值是function的key,將其放入finalReducers對象 if (typeof reducers[key] === "function") { finalReducers[key] = reducers[key] } }
2、校驗finalReducers, 判斷其每一個子reducer是否能返回正常的子state
//取出過濾出來的有效的keys列表 const finalReducerKeys = Object.keys(finalReducers) let unexpectedKeyCache if (process.env.NODE_ENV !== "production") { unexpectedKeyCache = {} } let shapeAssertionError try { assertReducerShape(finalReducers) } catch (e) { shapeAssertionError = e }
assertReducerShape函數:
//確認reducer是否是合法的reducer,即返回的state是不是undefined,如果是undefined,則是非法reducer function assertReducerShape(reducers) { Object.keys(reducers).forEach(key => { const reducer = reducers[key] const initialState = reducer(undefined, {type: ActionTypes.INIT}) if (typeof initialState === "undefined") { throw new Error( `Reducer "${key}" returned undefined during initialization. ` + `If the state passed to the reducer is undefined, you must ` + `explicitly return the initial state. The initial state may ` + `not be undefined. If you don"t want to set a value for this reducer, ` + `you can use null instead of undefined.` ) } const type = "@@redux/PROBE_UNKNOWN_ACTION_" + Math.random().toString(36).substring(7).split("").join(".") if (typeof reducer(undefined, {type}) === "undefined") { throw new Error( `Reducer "${key}" returned undefined when probed with a random type. ` + `Don"t try to handle ${ActionTypes.INIT} or other actions in "redux/*" ` + `namespace. They are considered private. Instead, you must return the ` + `current state for any unknown actions, unless it is undefined, ` + `in which case you must return the initial state, regardless of the ` + `action type. The initial state may not be undefined, but can be null.` ) } }) }三、分析combineReducers函數的返回值:
函數combination是一個標準的reducer函數,有初始化的state參數,和一個攜帶了actionType和數據的action對象。
function combination(state = {}, action) { //如果有非法的reducer,就直接報錯嘍 if (shapeAssertionError) { throw shapeAssertionError } if (process.env.NODE_ENV !== "production") { const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache) if (warningMessage) { warning(warningMessage) } } let hasChanged = false //定義新的nextState const nextState = {} // 1,遍歷reducers對象中的有效key, // 2,執行該key對應的value函數,即子reducer函數,并得到對應的state對象,即子state // 3,將新的子state掛到新的nextState對象上,key不變 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] = nextStateForKey //如果hasChanged為true,那就是true了 后面的判斷是,只要有一次nextStateForKey!== previousStateForKey不同,就說明整個state不同 hasChanged = hasChanged || nextStateForKey !== previousStateForKey } //如果state發生變化了,直接返回新的nextState,否則,還是返回舊的state return hasChanged ? nextState : state } }四、總結:
combineReducers函數其實就實現一個功能:將一個復雜的父reducer函數,根據state狀態對應的key,拆分成幾個子reducer;每個子reducer返回一個子state。多層嵌套的reducer樹,可以對應組成一個多層嵌套的state狀態樹。
完整解析請參考我的github:https://github.com/abczhijia/...,如果對您有幫助,歡迎star,有任何問題也請指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89067.html
摘要:大家好,今天給大家帶來的是的源碼分析首先是的地址點我接下來我們看看在項目中的簡單使用,一般我們都從最簡單的開始入手哈備注例子中結合的是進行使用,當然不僅僅能結合,還能結合市面上其他大多數的框架,這也是它比較流弊的地方首先是創建一個首先我們 大家好,今天給大家帶來的是redux(v3.6.0)的源碼分析~ 首先是redux的github地址 點我 接下來我們看看redux在項目中的簡單使...
摘要:接下來筆者就從源碼中探尋是如何實現的。其實很簡單,可以簡單理解為一個約束了特定規則并且包括了一些特殊概念的的發布訂閱器。新舊中存在的任何都將收到先前的狀態。這有效地使用來自舊狀態樹的任何相關數據填充新狀態樹。 Redux是當今比較流行的狀態管理庫,它不依賴于任何的框架,并且配合著react-redux的使用,Redux在很多公司的React項目中起到了舉足輕重的作用。接下來筆者就從源碼...
摘要:循環還沒有結束,其中的某個對進行了添加或者刪除,都會影響到此次循環的進行,帶來不可預期的錯誤。 首先來一段 redux 結合 中間件 thunk、logger 的使用demo 了解一下應該如何使用 const redux = require(redux) const { createStore, combineReducers, bindActionCreators, ...
摘要:循環還沒有結束,其中的某個對進行了添加或者刪除,都會影響到此次循環的進行,帶來不可預期的錯誤。 首先來一段 redux 結合 中間件 thunk、logger 的使用demo 了解一下應該如何使用 const redux = require(redux) const { createStore, combineReducers, bindActionCreators, ...
閱讀 2629·2021-11-23 09:51
閱讀 861·2021-09-24 10:37
閱讀 3612·2021-09-02 15:15
閱讀 1962·2019-08-30 13:03
閱讀 1881·2019-08-29 15:41
閱讀 2624·2019-08-29 14:12
閱讀 1424·2019-08-29 11:19
閱讀 3301·2019-08-26 13:39