7-多個Reducers的使用(combineReducers))

Time: 20200129

在前文我們知道,要新增一個買賣品類:冰激凌。

即增加一個reducer

但用一個reducer也能解決問題。我們先看這種方法是如何實現(xiàn)的。

代碼如下:

// index.js
// import redux from 'redux'

const redux = require('redux')  // nodejs version import
// this is a function
const createStore = redux.createStore // not redux.createStore()

// console.log("From index.js")

const BUY_CAKE = 'BUY_CAKE'
const BUY_ICECREAME = 'BUY_ICECREAM'

// action creator
function buyCake(params) {
    action = {
        type: BUY_CAKE,
        info: 'first redux action',
    }
    return action
}

function buyIceCream() {
    action = {
        type: BUY_ICECREAME,
        info: 'second redux action'
    }
    return action
}

// (previousState, action) => newState
const initialState = {
    numOfCakes: 10,
    numOfIceCreams: 20,
}
// 定義一個reducer,這里已經(jīng)把初始狀態(tài)放到reducer中了
const reducer = (state=initialState, action) => {
    switch (action.type) {
        case BUY_CAKE:
            return {
                ...state,
                numOfCakes: state.numOfCakes - 1
            }
        case BUY_ICECREAME:
            return {
                ...state,
                numOfIceCreams: state.numOfIceCreams - 1
            }
        default:
            return state
    }
}

// create a store
const store = createStore(reducer)
console.log('initial state: ', store.getState())
const unsubscribe = store.subscribe(() => console.log('Updated state', store.getState()))

store.dispatch(buyCake())
store.dispatch(buyCake())
store.dispatch(buyCake())

store.dispatch(buyIceCream())
store.dispatch(buyIceCream())

// 注銷監(jiān)聽事件
unsubscribe()  

執(zhí)行,node index.js,結(jié)果如下:

initial state:  { numOfCakes: 10, numOfIceCreams: 20 }
Updated state { numOfCakes: 9, numOfIceCreams: 20 }
Updated state { numOfCakes: 8, numOfIceCreams: 20 }
Updated state { numOfCakes: 7, numOfIceCreams: 20 }
Updated state { numOfCakes: 7, numOfIceCreams: 19 }
Updated state { numOfCakes: 7, numOfIceCreams: 18 }

多個reducers

為什么要拆分為多個reducers呢?

隨著要賣的產(chǎn)品的增多,相應(yīng)的處理函數(shù)也越來越多,這樣的話,一個reducer會越來越臃腫。

因此,適當拆分,代碼更易維護,且邏輯更加清晰。

其實拆分reducers和相應(yīng)的初始態(tài)并不難,需要思考的點在于,如何初始化一個store。

這就涉及到,combineReducers的使用了。

代碼總體如下:

// import redux from 'redux'

const redux = require('redux')  // nodejs version import
// this is a function
const createStore = redux.createStore // not redux.createStore()
const combineReducers = redux.combineReducers

// console.log("From index.js")
const BUY_CAKE = 'BUY_CAKE'
const BUY_ICECREAME = 'BUY_ICECREAM'

// action creator
function buyCake(params) {
    action = {
        type: BUY_CAKE,
        info: 'first redux action',
    }
    return action
}

function buyIceCream() {
    action = {
        type: BUY_ICECREAME,
        info: 'second redux action'
    }
    return action
}

// (previousState, action) => newState
// const initialState = {
//     numOfCakes: 10,
//     numOfIceCreams: 20,
// }
// 拆分為多個初始狀態(tài)
const initialCakeState = {
    numOfCakes: 10,
}
const initialIceCreamState = {
    numOfIceCreams: 20,
}

// 定義一個reducer,這里已經(jīng)把初始狀態(tài)放到reducer中了
// const reducer = (state=initialState, action) => {
//     switch (action.type) {
//         case BUY_CAKE:
//             return {
//                 ...state,
//                 numOfCakes: state.numOfCakes - 1
//             }
//         case BUY_ICECREAME:
//             return {
//                 ...state,
//                 numOfIceCreams: state.numOfIceCreams - 1
//             }
//         default:
//             return state
//     }
// }
// 拆分reducers
const cakeReducer = (state=initialCakeState, action) => {
    switch (action.type) {
        case BUY_CAKE:
            return {
                ...state,
                numOfCakes: state.numOfCakes - 1
            }
        default:
            return state
    }
}
const iceCreamReducer = (state=initialIceCreamState, action) => {
    switch (action.type) {
        case BUY_ICECREAME:
            return {
                ...state, 
                numOfIceCreams: state.numOfIceCreams - 1
            }
        default:
            return state
    }
}
const rootReducer = combineReducers({
    cake: cakeReducer,
    iceCream: iceCreamReducer
})
// create a store
// const store = createStore(reducer)
const store = createStore(rootReducer)

console.log('initial state: ', store.getState())
const unsubscribe = store.subscribe(() => console.log('Updated state', store.getState()))

store.dispatch(buyCake())
store.dispatch(buyCake())
store.dispatch(buyCake())

store.dispatch(buyIceCream())
store.dispatch(buyIceCream())

// 注銷監(jiān)聽事件
unsubscribe()  

執(zhí)行結(jié)果會略有不同:

initial state:  { cake: { numOfCakes: 10 }, iceCream: { numOfIceCreams: 20 } }
Updated state { cake: { numOfCakes: 9 }, iceCream: { numOfIceCreams: 20 } }
Updated state { cake: { numOfCakes: 8 }, iceCream: { numOfIceCreams: 20 } }
Updated state { cake: { numOfCakes: 7 }, iceCream: { numOfIceCreams: 20 } }
Updated state { cake: { numOfCakes: 7 }, iceCream: { numOfIceCreams: 19 } }
Updated state { cake: { numOfCakes: 7 }, iceCream: { numOfIceCreams: 18 } }

抽出來看就是,這個狀態(tài)樹不再是扁平的,而是按照combineReducers時指定的鍵名來劃分小區(qū)間了。

{ 
  cake: { numOfCakes: 7 }, 
  iceCream: { numOfIceCreams: 18 } 
}

這個特性曾經(jīng)在我寫項目的時候,困擾了我一段時間,最后知道了這個特性才弄懂狀態(tài)樹的使用方式。

combineReducers

const combineReducers = redux.combineReducers
const rootReducer = combineReducers({
    cake: cakeReducer,
    iceCream: iceCreamReducer
})
const store = createStore(rootReducer)

END.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容