开发者问题收集

TypeError:未定义不是对象(评估'state.selectedData.push') - 无法使用 Redux Toolkit 将有效负载添加到状态

2022-01-05
1193

我在使用 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 };

更新

我做了很好的旧删除并重新添加,现在它可以正常工作了。重命名切片/减速器,因为它与另一个组件同名(感觉很奇怪,但这可能是问题所在?)。我已将旧代码与现在的工作代码进行了比较,没有发现任何区别,因此我最好的猜测是重命名是问题所在。

3个回答

Redux 会按顺序将状态数据序列化(转换为字符串)并保存在异步存储中。序列化后,您将无法访问数组方法,包括 Array.push

尝试在使用数组方法之前解析数组。

saveSelectedItemIdsToRedux: (state, action) => {

const serializedData = JSON.parse(state.selectedData)

state.selectedData = serializedData.push(action.payload);

        }

注意: 当您使用带有嵌套对象的数组时,JSON.parse 有时会失败。

Fiston Emmanuel
2022-01-05

希望这有帮助!删除箭头函数并像

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;
        }

    },

}
一样使用它
Basava
2022-01-05

我遇到了同样的问题,并弄清楚了这一点:使用 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

Guillermo Mata
2022-05-05