loading...
上次更新: 2024-05-10
備註:此篇範例是在
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 來實作前面蛋糕店、冰淇淋店的例子。npm i @reduxjs/toolkit
Redux-toolkit 提供了一個建議的資料夾結構,以協助組織 Redux 相關的程式碼。/app
- index.js
/feautures
/cake
/iceCream
說明:
redux-toolkit 中,建議把一個功能的 reducer 邏輯和 action 放在一起,且檔案名稱以 slice 作為後綴。slice 來管理狀態。cake 資料夾底下,新增 cakeSlice.js引入 createSlice
// features/cakes/cakeSlice.js
// (因為是 node 環境,所以用 require)
const createSlice = require("@reduxjs/toolkit").createSlice;createSlice 接收一個物件,此物件包含三個參數:
// features/cakes/cakeSlice.js
const cakeSlice = createSlice({
name: "cake", // slice的名字
initialState: { // 初始狀態
numOfCakes: 10,
},
reducers: {} // 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 寫法:
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;
},
},
});我們寫了 reducers,它會自動幫我們產生 action creator,名稱就和 reducers 裡定義的 key 相同 (order 和 restock)。
因此我們就不用再自己創建 action type 常數、action creator...等了。
// features/cakes/cakeSlice.js
module.exports = cakeSlice.reducer;
module.exports.cakeActions = cakeSlice.actions;store.js ,使用 configureStore 來創建 storereducer 屬性,我們把 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;redux 一樣,使用 getState() 來得到狀態;使用 subscribe() 來註冊。(詳見 Redux#2 Store, Action, Reudcer 基本寫法)dispatch() 來發送 actionredux-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 reducerstate,不用擔心 mutable 物件問題configureStore 來創建 storestore.getState() 取得狀態store.subscribe() 偵測狀態改變store.dispatch() 改變狀態參考資料: