Vì reducer của RTK được bọc bởi Immer.
- Cái bạn nhận không phải state thật mà là draft proxy: mọi thao tác "mutate" được ghi lại, sau đó Immer tạo ra state mới, chỉ copy những nhánh thực sự đổi (structural sharing).
- Store vẫn nhận về object bất biến hoàn toàn mới.
reducers: {
addItem(state, action) {
state.items.push(action.payload) // an toàn: đang mutate draft
},
}Ba bẫy hay gặp:
1. Vừa mutate vừa return. Trong một reducer, hoặc mutate draft, hoặc return state mới — làm cả hai thì Immer ném lỗi. Ngoại lệ hợp lệ: return initialState để reset.
2. Gán vào biến rồi mutate biến đó. const arr = state.items; arr = [...] không thay đổi gì cả, vì gán lại biến cục bộ chứ không ghi vào draft. Phải viết state.items = [...].
3. Immer chỉ hoạt động bên trong createSlice/createReducer. Trong component hoặc hàm helper ngoài reducer, không có draft — mutate ở đó là mutate thật, vi phạm immutability và có thể gây bug không re-render.
Cũng lưu ý: không được đưa giá trị không serialize được (Date, Map, class instance, Promise) vào state — RTK bật middleware cảnh báo mặc định vì DevTools và persist đều cần state serialize được.