前言:Redux Toolkit
算是專案上很常用到的 Tool,我們過往在對資料進行整理時都會遇到 Redux
要求我們資料不能直接 mutable
,因此我們就必須針對陣列或是物件進行解構
而這樣當然可以 work ,而 Immer.js
提供我們一個更好的方式來處理 mutable
資料
參考資料:
Redux Toolkit 官網介紹
Redux Rules
- reducers are never allowed to mutate the original / current state values
1 | // illegal |
- old written rules
1 | // ✅ This is safe, because we made a copy |
Redux with Immer.js
immer.js 提供 produce
function,接受兩個參數。第一個是, 原本的 state
(immutable),第二個是 callback function。在 callback 中他會接受 草稿(未更新) state,而我們可以在這裡進行 mutate 操作。
⇒ 表面上看起來是 mutate 操作,但實際上不是。
而我們在 CreateReducer API 內部已經提供內建 immer.js
Immer.js Usaga Patterns
記得 mutate 必須是 object 或是 array
Immer expects that you will
either *mutate* the existing state
, or construct a new state value yourself and return it
, but not both in the same function!Arrow function 不能 return,因為 immer.js 會遇到
attemped value
跟 回傳value
。他不知道要用哪一個 ⇒ 可是專案這樣寫卻不會錯,我也不知道為什麼1
2
3
4
5
6
7
8
9
10
11
12
13export const solutionSlice = createSlice({
name: 'calculator',
initialState: {
solutionData: []
},
reducers: {
getSolutionData: (_state, action) => ({ ..._state }),
setSolutionData: (state, action) => {
const { solutionData, saleTags } = action.payload;
return { ...state, solutionData, saleTags };
}
}
});遇到巢狀可以這樣寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function objectCaseReducer1(state, action) {
const { a, b, c, d } = action.payload
return {
...state,
a,
b,
c,
d,
}
}
function objectCaseReducer2(state, action) {
const { a, b, c, d } = action.payload
// This works, but we keep having to repeat `state.x =`
state.a = a
state.b = b
state.c = c
state.d = d
}
function objectCaseReducer3(state, action) {
const { a, b, c, d } = action.payload
Object.assign(state, { a, b, c, d })
}如果要更新或取代,就必須這樣寫,必須要
return
1 | const initialState = [] |