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.