#javascript #reactjs #redux #redux-persist #redux-offline
Вопрос:
После очистки состояния приложения в инструментах разработки или первого посещения сайта получите эти ошибки в консоли. Состояние по умолчанию-это неспособность загрузить объект, который является нулевым или неопределенным.
Хранилище настроено с помощью 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();
Store code:
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;
Начальное состояние записи щелчка:
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,
};
Начальное состояние учетной записи пользователя:
export interface UserState {
account?: IUser | null;
}
const initialState: UserState = {};
Комментарии:
1. Решено: мне не удалось установить значение persist в значение undefined в автономной конфигурации, поэтому между redux persist v5 и v6 возник конфликт поведения. Необходимо добавить
persist: undefined
в автономную конфигурацию.enhancers: [offline({ ...config, persist: undefined, effect }) as StoreEnhancer],