1
2024-05-10
#Redux

Redux#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

  1. 開啟一個新專案,並安裝 redux-toolkit
npm i @reduxjs/toolkit
  1. 資料夾結構
  • 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 接收一個物件,此物件包含三個參數:

  1. slice的名字
  2. 初始狀態
  3. 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;
  }
};

使用 createSlicereducer 寫法:

  1. 處理蛋糕下單,我們使用 order 做為 key,而 value 會是一個函式,此函式接收 state action 做為參數
  2. 不同於之前的寫法,使用了 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() 改變狀態

參考資料:

main*
© 2024 All Rights Reserved. IRIS Studio