回首我們目前的功能已經相對完善許多,但站在維護的角度,我們應該可以做得更好一些!
程式語言畢竟還是語言,既然是語言,我們能做的就是讓其更加言之有物,這樣也比較方便後續的維護,依照這樣的思維,我們再回到我們已經完成的 orderReducer 去看,是不是會覺得這個檔案和我們賦予他的名字對不太上啊,憑什麼要 order 去處理 restock 的工作勒,作為一名資深社畜肯定是不幹的,所以寫程式也得講究個名正言順!
那我們就將原本在 initialState 的 key 都獨立開來,讓他們各自爲政,來模擬一下之後專案複雜化的情境,以 numOfCoffee 為例,我們重新新增一個 reducer 檔案叫 coffeeReducer.js,那他的工作只需要控制咖啡的數量就好,如以下:
// coffeeReducer.js
const { COFFEE_ORDERED, COFFEE_RESTOCKED } = require("../action/types")
const initialState = {
numOfCoffee: 20
}
const coffeeReducer = (state = initialState, action) => {
switch (action.type) {
case COFFEE_ORDERED:
return {
...state,
numOfCoffee: state.numOfCoffee - action.payload.qty,
}
case COFFEE_RESTOCKED:
return {
...state,
numOfCoffee: state.numOfCoffee + action.payload.qty
}
default:
return state;
}
}
module.exports = { coffeeReducer }
一樣的概念我們將咖啡豆也拆出來,如下:
// coffeeBeanReducer.js
const { COFFEEBEAN_ORDERED, COFFEEBEAN_RESTOCKED } = require("../action/types")
const initialState = {
numOfCoffeeBean: 20
}
const coffeeBeanReducer = (state = initialState, action) => {
switch (action.type) {
case COFFEEBEAN_ORDERED:
// 顧客買 => 商品-, 營收+
return {
...state,
numOfCoffeeBean: state.numOfCoffeeBean - action.payload.qty
}
case COFFEEBEAN_RESTOCKED:
// 補貨 => 商品+, 營收-
return {
...state,
numOfCoffeeBean: state.numOfCoffeeBean + action.payload.qty
}
default:
return state;
}
}
module.exports = { coffeeBeanReducer }
接著處理蛋糕的部分:
// cakeReducer.js
const { CAKE_ORDERED, CAKE_RESTOCKED } = require("../action/types")
const initialState = {
numOfCake: 20
}
const cakeReducer = (state = initialState, action) => {
switch (action.type) {
case CAKE_ORDERED:
// 顧客買 => 商品-, 營收+
return {
...state,
numOfCake: state.numOfCake - action.payload.qty,
}
case CAKE_RESTOCKED:
// 補貨 => 商品+, 營收-
return {
...state,
numOfCake: state.numOfCake + action.payload.qty,
}
default:
return state;
}
}
module.exports = { cakeReducer }
最後,還有營收的部分,這邊不管哪個動作都跟營收有關,所以他的 case 也會很多,我們姑且取名為 assetsReducer.js,如下:
// assetsReducer.js
const { COFFEE_ORDERED, COFFEE_RESTOCKED, COFFEEBEAN_ORDERED, COFFEEBEAN_RESTOCKED, CAKE_ORDERED, CAKE_RESTOCKED } = require("../action/types");
const initialState = {
assets: 1000,
}
// 這部分和useReducer hook是一樣的
const assetsReducer = (state = initialState, action) => {
switch(action.type) {
case COFFEE_ORDERED:
// 顧客買 => 商品-, 營收+
return {
...state,
assets: state.assets + action.payload.income
}
case COFFEE_RESTOCKED:
// 補貨 => 商品+, 營收-
return {
...state,
assets: state.assets - action.payload.pay
}
case COFFEEBEAN_ORDERED:
// 顧客買 => 商品-, 營收+
return {
...state,
assets: state.assets + action.payload.income
}
case COFFEEBEAN_RESTOCKED:
// 補貨 => 商品+, 營收-
return {
...state,
assets: state.assets - action.payload.pay
}
case CAKE_ORDERED:
// 顧客買 => 商品-, 營收+
return {
...state,
assets: state.assets + action.payload.income
}
case CAKE_RESTOCKED:
// 補貨 => 商品+, 營收-
return {
...state,
assets: state.assets - action.payload.pay
}
default:
return state;
}
}
module.exports = { assetsReducer }
接著我們來調整一下我們的 reducers 的組成,將原本的 orderReducer 置換掉:
// reducer/index.js
const { combineReducers } = require("redux");
const { assetsReducer } = require("./assetsReducer");
const { cakeReducer } = require("./cakeReducer");
const { coffeeBeanReducer } = require("./coffeeBeanReducer");
const { coffeeReducer } = require("./coffeeReducer");
const reducers = combineReducers({
coffee: coffeeReducer,
coffeeBean: coffeeBeanReducer,
cake: cakeReducer,
money: assetsReducer,
})
module.exports = {
reducers
}
完成後,我們來測試看看結果:
initial state {
coffee: { numOfCoffee: 20 },
coffeeBean: { numOfCoffeeBean: 20 },
cake: { numOfCake: 20 },
money: { assets: 1000 }
}
更新 {
coffee: { numOfCoffee: 18 },
coffeeBean: { numOfCoffeeBean: 20 },
cake: { numOfCake: 20 },
money: { assets: 1020 }
}
更新 {
coffee: { numOfCoffee: 38 },
coffeeBean: { numOfCoffeeBean: 20 },
cake: { numOfCake: 20 },
money: { assets: 1010 }
}
更新 {
coffee: { numOfCoffee: 38 },
coffeeBean: { numOfCoffeeBean: 17 },
cake: { numOfCake: 20 },
money: { assets: 1025 }
}
更新 {
coffee: { numOfCoffee: 38 },
coffeeBean: { numOfCoffeeBean: 27 },
cake: { numOfCake: 20 },
money: { assets: 1015 }
}
更新 {
coffee: { numOfCoffee: 38 },
coffeeBean: { numOfCoffeeBean: 27 },
cake: { numOfCake: 18 },
money: { assets: 1045 }
}
更新 {
coffee: { numOfCoffee: 38 },
coffeeBean: { numOfCoffeeBean: 27 },
cake: { numOfCake: 23 },
money: { assets: 1020 }
}
出現以上訊息的話代表你成功了,至此我們已經學會如何管理多個 reducer 了,下一篇我們嘗試透過 redux-thunk 來處理一些異步處理的 function。