Redux Toolkit如何更新initialState中未预定义的状态对象
问题背景
数据为动态传入,无法提前知晓其值以在initialState中完成初始赋值,触发运行时报错。
核心疑问:如果initialState中原本不存在对应对象,要如何更新state中的该对象?
报错信息
filteringSlice.ts:12 Uncaught TypeError: Cannot read properties of undefined (reading 'products') at addFilter (filteringSlice.ts:12:1) at createReducer.ts:280:1 at produce (immerClass.ts:94:1) at createReducer.ts:279:1 at Array.reduce (<anonymous>) at reducer (createReducer.ts:246:1) at reducer (createSlice.ts:325:1) at combination (redux.js:560:1) at k (<anonymous>:2235:16) at D (<anonymous>:2251:13)
Action调用示例
onChange={(selectedValue) => { dispatch( addFilter({ products: { category__name: { filter: selectedValue } }, }) ); }}
Slice原代码定义
import { createSlice } from "@reduxjs/toolkit"; const initialState = {} as any; const filteringSlice = createSlice({ name: "filtering", initialState, reducers: { addFilter: (state, action) => { const key = Object.keys(action.payload)[0]; const key2 = Object.keys(action.payload[key])[0]; const values = Object.values(action.payload[key])[0]; //@ts-ignore state.filters[key][key2] = { ...state.filters[key][key2], ...values }; }, }, }); const { reducer, actions } = filteringSlice; export const { addFilter } = actions; export default reducer;
报错原因
- 初始
initialState是空对象,根本没有filters属性,第一次执行addFilter时直接访问state.filters[key],相当于读取undefined[key],直接触发类型错误。 - 动态key场景下没有做上层对象的存在性校验,直接访问嵌套属性,只要上层对象不存在就会抛错。
修复方案
- 先给initialState补上基础的
filters空对象结构,避免最上层属性不存在。 - 赋值前先判断每层动态key对应的对象是否存在,不存在就初始化为空对象,再做属性合并,适配动态传入的任意key场景。
修复后的Slice代码:
import { createSlice } from "@reduxjs/toolkit"; // 先初始化基础的filters结构 const initialState = { filters: {} } as any; const filteringSlice = createSlice({ name: "filtering", initialState, reducers: { addFilter: (state, action) => { const key = Object.keys(action.payload)[0]; const key2 = Object.keys(action.payload[key])[0]; const values = Object.values(action.payload[key])[0]; // 动态key不存在时先初始化空对象,避免读取undefined属性 if (!state.filters[key]) { state.filters[key] = {}; } if (!state.filters[key][key2]) { state.filters[key][key2] = {}; } state.filters[key][key2] = { ...state.filters[key][key2], ...values }; }, }, }); const { reducer, actions } = filteringSlice; export const { addFilter } = actions; export default reducer;
如果不想写多层if判断,也可以用简写方式:
addFilter: (state, action) => { const key = Object.keys(action.payload)[0]; const key2 = Object.keys(action.payload[key])[0]; const values = Object.values(action.payload[key])[0]; state.filters[key] = state.filters[key] || {}; state.filters[key][key2] = { ...(state.filters[key][key2] ?? {}), ...values }; }
内容的提问来源于stack exchange,提问作者skelaw
相关产品推荐
相关产品推荐

