首页 > 解决方案 > Redux persist v6 defaultStateReconciler TypeError: Cannot convert undefined or null to object when first visit web application

问题描述

在开发工具中清除应用程序状态后,或第一次访问站点后,在控制台中收到这些错误。默认状态是无法加载空或未定义的对象。

store 配置 redux-offline,使用 redux-persist v6 和 redux 工具包

我尝试确保我的 createSelector 调用没有 null 初始值。刷新页面会清除错误,并且应用程序的所有后续使用都是无错误的。

控制台截图

autoRehydrate.js:54 Uncaught (in promise) TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at defaultStateReconciler (autoRehydrate.js:54)
    at autoRehydrate.js:38
    at computeNextEntry (<anonymous>:3395:21)
    at recomputeStates (<anonymous>:3429:17)
    at <anonymous>:3809:22
    at Object.dispatch (redux.js:288)
    at dispatch (<anonymous>:3856:17)
    at middleware.js:28
    at redux-toolkit.esm.js:376
    at index.js:11
    at Object.dispatch (redux-toolkit.esm.js:314)
    at Object.dispatch (<anonymous>:14608:80)
    at Object.rehydrate (persistStore.js:77)
    at _rehydrate (persistReducer.js:61)
    at persistReducer.js:90
autoRehydrate.js:54 Uncaught TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at defaultStateReconciler (autoRehydrate.js:54)
    at autoRehydrate.js:38
    at computeNextEntry (<anonymous>:3395:21)
    at recomputeStates (<anonymous>:3429:17)
    at <anonymous>:3809:22
    at Object.dispatch (redux.js:288)
    at dispatch (<anonymous>:3856:17)
    at middleware.js:28
    at redux-toolkit.esm.js:376
    at index.js:11
    at Object.dispatch (redux-toolkit.esm.js:314)
    at Object.dispatch (<anonymous>:14608:80)
    at Object.rehydrate (persistStore.js:77)
    at _rehydrate (persistReducer.js:61)
    at persistReducer.js:67

应用索引:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "semantic-ui-css/semantic.min.css";
import { BrowserRouter } from "react-router-dom";
import { PersistGate } from "redux-persist/integration/react";
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";

// import redux
import { store, persistor } from "./config/redux/store";
import { Provider } from "react-redux";

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>
                <BrowserRouter>
                    <App />
                </BrowserRouter>
            </PersistGate>
        </Provider>
    </React.StrictMode>,
    document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorkerRegistration.register();

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
reportWebVitals();

店铺代码:

import axios, { AxiosRequestConfig } from "axios";
import { AnyAction, Reducer } from "redux";
import {
    combineReducers,
    configureStore,
    StoreEnhancer,
} from "@reduxjs/toolkit";
import { offline } from "@redux-offline/redux-offline";
import config from "@redux-offline/redux-offline/lib/defaults";

import userReducer from "./userSlice";
import noteReducer from "./noteSlice";
import { OfflineAction } from "@redux-offline/redux-offline/lib/types";

import storage from "redux-persist/lib/storage";
import {
    persistStore,
    persistReducer,
    FLUSH,
    REHYDRATE,
    PAUSE,
    PERSIST,
    PURGE,
    REGISTER,
} from "redux-persist";

// _action variable used for redux-offline
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const effect = (effect: AxiosRequestConfig, _action: OfflineAction) =>
    axios({ ...effect, withCredentials: true });

const combinedReducer = combineReducers({
    user: userReducer,
    notes: noteReducer,
});

export const RESET_BASE = "reset/all";
const rootReducer: Reducer = (state: RootState, action: AnyAction) => {
    if (action.type === RESET_BASE) {
        state = {} as RootState;
    }
    return combinedReducer(state, action);
};

const persistConfig = {
    key: "root",
    storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
    reducer: persistedReducer,
    enhancers: [offline({ ...config, effect }) as StoreEnhancer],
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware({
            serializableCheck: {
                ignoredActions: [
                    FLUSH,
                    REHYDRATE,
                    PAUSE,
                    PERSIST,
                    PURGE,
                    REGISTER,
                ],
            },
        }),
});

export const persistor = persistStore(store);

export type RootState = ReturnType<typeof store.getState>;
export interface RootStateWithOffline extends RootState {
    offline: {
        busy: boolean;
        lastTransaction: number;
        online: boolean;
        outbox: Array<ReturnType<typeof effect>>;
        retryCount: number;
        retryScheduled: boolean;
    };
}
export type AppDispatch = typeof store.dispatch;

noteSlice 的初始状态:

export interface NoteState {
    array: Array<INote>;
    stringMap: StringMap;
    tempMap: StringMap;
    columnDict: ColumnDict;
    filter: string;
    search: string;
    searchLoading: boolean;
    editing?: INote | null;
}

const initialState: NoteState = {
    array: [],
    stringMap: { arr1: [], arr2: [], arr3: [] },
    tempMap: { arr1: [], arr2: [], arr3: [] },
    columnDict: {
        ["col1"]: {
            name: "col1",
            items: [],
        },
        ["col2"]: {
            name: "col2",
            items: [],
        },
        ["col3"]: {
            name: "col3",
            items: [],
        },
    },
    filter: "",
    search: "",
    searchLoading: false,
};

userSlice 的初始状态:

export interface UserState {
    account?: IUser | null;
}

const initialState: UserState = {};

标签: javascriptreactjsreduxredux-persistredux-offline

解决方案


推荐阅读