2024-05-10
#ReduxRedux#6 Redux-toolkit 使用步驟
備註:此篇範例是在
node.js
的環境跑
Demo:https://codesandbox.io/p/sandbox/redux-6-redux-toolkit-yyy4r2
#前言
- 在
Redux
中,有許多重複性高的模板code (boilerplate code)。像我們每次都要創建一個action
物件、action creator
、在reducer
裡使用 switch case 來改變state
...等。在專案中重複這些動作是很不方便的事。 - 使用
Redux-toolkit
可以讓開發變得更加有效率。 - 在這個章節會使用
Redux-toolkit
來實作前面蛋糕店、冰淇淋店的例子。
#- step0. 專案 set up
- 開啟一個新專案,並安裝 redux-toolkit
npm i @reduxjs/toolkit
- 資料夾結構
Redux-toolkit
提供了一個建議的資料夾結構,以協助組織Redux
相關的程式碼。- 建議的資料夾結構通常是基於功能的(feature),所有關於同個功能的檔案放在同一個資料夾。
/app
- index.js
/feautures
/cake
/iceCream
#- step1. createSlice
說明:
- 在
redux-toolkit
中,建議把一個功能的reducer
邏輯和action
放在一起,且檔案名稱以slice
作為後綴。 - 把應用程式分成一個個的
slice
來管理狀態。 - 我們在
cake
資料夾底下,新增cakeSlice.js
引入 createSlice
// features/cakes/cakeSlice.js
// (因為是 node 環境,所以用 require)
const createSlice = require("@reduxjs/toolkit").createSlice;
createSlice 接收一個物件,此物件包含三個參數:
- slice的名字
- 初始狀態
- reducers
// features/cakes/cakeSlice.js
const cakeSlice = createSlice({
name: "cake", // slice的名字
initialState: { // 初始狀態
numOfCakes: 10,
},
reducers: {} // reducers
});
#- step2. reducers 內容
在前面不使用 redux-toolkit
時,我們用 switch case
來處理。
// features/cakes/cakeSlice.js
const cakeReducer = (prevState = cakeState, action) => {
switch (action.type) {
case "CAKE_ORDER":
const cakeQuantity = action.payload.quantity;
return {
...prevState,
cakes: prevState.cakes - cakeQuantity
};
default:
return prevState;
}
};
使用 createSlice
的 reducer
寫法:
- 處理蛋糕下單,我們使用 order 做為 key,而 value 會是一個函式,此函式接收
state
action
做為參數 - 不同於之前的寫法,使用了
createSlice
,我們可以直接改變state
,不用 return 新的狀態。 (redux-toolkit
使用了 Immer,因此我們可以直接改變狀態)
// features/cakes/cakeSlice.js
const cakeSlice = createSlice({
name: "cake",
initialState: {
numOfCakes: 10,
},
reducers: {
order: (state, action) => {
state.numOfCakes -= action.payload.quantity;
},
restock: (state, action) => {
state.numOfCakes += action.payload.quantity;
},
},
});
那麼 action 呢?
我們寫了 reducers
,它會自動幫我們產生 action creator,名稱就和 reducers
裡定義的 key 相同 (order 和 restock)。
因此我們就不用再自己創建 action type 常數、action creator...等了。
export actions 和 reducers
// features/cakes/cakeSlice.js
module.exports = cakeSlice.reducer;
module.exports.cakeActions = cakeSlice.actions;
#- step3. 創建 store
- 我們要在
store.js
,使用 configureStore 來創建 store - configureStore 接收一個物件,裡面有個
reducer
屬性,我們把 slices 的 reducer 設置在這邊。
// app/store.js
const configureStore = require("@reduxjs/toolkit").configureStore;
const cakeReducer = require("../features/cakes/cakeSlice");
const store = configureStore({
reducer: {
cake: cakeReducer,
},
});
module.exports = store;
#- step4. 使用 store
- 如同單純
redux
一樣,使用getState()
來得到狀態;使用subscribe()
來註冊。(詳見 Redux#2 Store, Action, Reudcer 基本寫法) - 使用
dispatch()
來發送action
- 直接使用
redux-toolkit
幫我們產生的 action creator
// index.js
const store = require("./app/store");
const cakeActions = require("./features/cakes/cakeSlice").cakeActions;
// 取得狀態
console.log("Initial State:", store.getState());
// 偵測狀態改變
const unsubscribe = store.subscribe(() => {
console.log("Updated State:", store.getState());
});
// 改變狀態(下單蛋糕,數量減3)
store.dispatch(
cakeActions.order({
quantity: 3,
}),
);
// 改變狀態(蛋糕補貨,數量加10)
store.dispatch(
cakeActions.restock({
quantity: 10,
}),
);
unsubscribe();
console 結果如下
Initial State: { cake: { numOfCakes: 10 } }
Updated State: { cake: { numOfCakes: 7 } }
Updated State: { cake: { numOfCakes: 17 } }
#總結 redux-toolkit
的使用方法
- 使用
createSlice
,它會產生 action reducer - 可以直接改變
state
,不用擔心 mutable 物件問題 - 使用
configureStore
來創建store
store.getState()
取得狀態store.subscribe()
偵測狀態改變store.dispatch()
改變狀態
參考資料: