TypeError:未定义不是对象(评估'state.selectedData.push') - 无法使用 Redux Toolkit 将有效负载添加到状态
我在使用 Redux Toolkit 时遇到了问题。我想将一个称为 selectedData 的对象推送到我的初始状态,这是一个数组,这给了我错误“TypeError:undefined 不是对象(评估‘state.selectedData.push’)”。
我一直在关注 https://redux-toolkit.js.org/usage/immer-reducers ,他们编写的 Reducer 逻辑与我的完全相同。我不知道为什么它对我不起作用。
他们的代码示例:
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
todoAdded(state, action) {
// "Mutate" the existing state, no return value needed
state.push(action.payload)
},
todoDeleted(state, action.payload) {
// Construct a new result array immutably and return it
return state.filter(todo => todo.id !== action.payload)
}
}
})
我的代码
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
export const exerciseItemSlice = createSlice({
name: "exerciseItem",
initialState: { selectedData: [] },
reducers: {
saveSelectedItemIdsToRedux: (state, action) => {
state.selectedData.push(action.payload);
},
resetSelectedItemIds(state, action) {
return state.itemSelectedData;
}
},
}
);
// Action creators are generated for each case reducer function
export const { saveSelectedItemIdsToRedux, resetSelectedItemIds } = exerciseItemSlice.actions;
export default exerciseItemSlice.reducer;
唯一的区别是我传递了一个名为 selectedData 的状态,我也尝试过仅使用 initialState。
编辑:使用所有相关代码进行更新,因为问题无法通过上述代码重现,这表明问题应该在其他地方?
rootReducer.js
import counterReducer from "./counterSlice";
import texterReducer from "./testSlice";
import setsTextReducer from "./setsTextSlicer";
import templateReducer from "./templateSlice";
import setsScreenReducer from "./setsScreenSlice";
import exerciseBrowserReducer from "./exerciseBrowserSlice";
import exerciseItemReducer from "./exerciseItemSlice";
import { combineReducers } from "redux";
const rootReducer = combineReducers({
counter: counterReducer,
texter: texterReducer,
setsText: setsTextReducer,
template: templateReducer,
setsScreen: setsScreenReducer,
exercise: exerciseBrowserReducer,
exerciseItem: exerciseItemReducer,
});
export default rootReducer;
store.js
import { configureStore } from "@reduxjs/toolkit";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist'
import AsyncStorage from "@react-native-async-storage/async-storage";
import rootReducer from "./rootReducer";
const persistConfig = {
key: 'root',
version: 1,
storage: AsyncStorage,
//blacklist: [rootReducer.exerciseItem]
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
// https://github.com/reduxjs/redux-thunk
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
})
});
export const persistor = persistStore(store);
export { store };
更新
我做了很好的旧删除并重新添加,现在它可以正常工作了。重命名切片/减速器,因为它与另一个组件同名(感觉很奇怪,但这可能是问题所在?)。我已将旧代码与现在的工作代码进行了比较,没有发现任何区别,因此我最好的猜测是重命名是问题所在。
Redux 会按顺序将状态数据序列化(转换为字符串)并保存在异步存储中。序列化后,您将无法访问数组方法,包括
Array.push
。
尝试在使用数组方法之前解析数组。
saveSelectedItemIdsToRedux: (state, action) => {
const serializedData = JSON.parse(state.selectedData)
state.selectedData = serializedData.push(action.payload);
}
注意: 当您使用带有嵌套对象的数组时,JSON.parse 有时会失败。
希望这有帮助!删除箭头函数并像
export const exerciseItemSlice = createSlice({
name: "exerciseItem",
initialState: { selectedData: [] },
reducers: {
// below line is the change
saveSelectedItemIdsToRedux(state, action){
state.selectedData.push(action.payload);
},
resetSelectedItemIds(state, action) {
return state.itemSelectedData;
}
},
}
一样使用它
我遇到了同样的问题,并弄清楚了这一点:使用 redux-toolkit,每个 Reducer 都拥有自己的状态片段,因此当您在 中调用 state 时
state.selectedData.push(action.payload);
您实际上是在调用 State => selectedData => selectedData,这是未定义的
要在 Reducer 函数中使用您的 selectedData,请使用 createSlice API 调用 state,这意味着 State => selectedData。
然后您必须从此更改为:
reducers: {
saveSelectedItemIdsToRedux: (state, action) => {
state.selectedData.push(action.payload);
},
resetSelectedItemIds(state, action) {
return state.itemSelectedData;
}
},
为此
reducers: {
saveSelectedItemIdsToRedux: (state, action) => {
state.push(action.payload);
},
resetSelectedItemIds(state, action) {
return state;
}
},
它将起作用 :-D