extraReducer: reducer 的進化版
extraReducer 行為
extraReducer 會偵測 全局 的 action,再對自己身處的 slice 做 state 更新
extraReducer 也可以處理 非同步 操作,需要搭配 createAsyncThunk
extraReducer 有使用 Immer 協助,可以直接做類似 mutating 的操作
extraReducer 可以定義預設行為
That means many different slice reducers can all respond to the same dispatched action, and each slice can update its own state if needed!
與 reducer 不同
extraReducer 不會產生新的 action type
如果 reducer、extraReducer 對同一個 action type 定義,會以 reducer 執行
extraReducer 使用
本篇文主要介紹兩個 extraReducer 的功用 處理非同步邏輯、監聽全域的 Action
實際上還有其他應用,可以直接看官網
extraReducer 處理非同步
以下例子為,機器狀態必須透過 API (非同步)的回應來取得
fetchMachineData 必須處理非同步的事件,因此要用 createAsyncThunk 創建。當請求成功時,會進入 fulfilled 的邏輯,反之,失敗會進入 rejected。
createAsyncThunk 的介紹可以參考這篇。
machineSlice.ts
export const fetchMachineData = createAsyncThunk<MachineState, string>('../fetchData', async (stateId: string) => {
if (MACHINE_STATE.includes(stateId)) {
const resp = await ...;
return parseData(resp.payload) as MachineState;
}
return {
...
} as MachineState;
});
const machineSlice = createSlice({
name: 'machine',
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchMachineData.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchMachineData.fulfilled, (state, action) => {
const { data } = action.payload;
state.data = data;
})
.addCase(fetchMachineData.rejected, (state) => {
state.data = null;
});
},
});