Redux-Persist не сохраняет состояние в локальном хранилище

Я пытаюсь сохранить определенное состояние редуктора в localStorage, чтобы оно не исчезало, даже если браузер обновляется.

Я написал некоторый код, но в хранилище я вижу только следующее:

"persist:root", "{"_persist":{\"version\":-1,\"rehydrated\":true}"}"

Нет user данных. Что мне не хватает?

К вашему сведению, причина, по которой мне нужно хранить пользовательские данные как глобальную переменную, заключается в том, что мне приходится выполнять повторный рендеринг в зависимости от этого значения. Проблема в том, что при обновлении браузера он продолжает переход к странице входа в систему. Я проверил инструменты разработки Redux, пользовательские данные установлены правильно в компоненте Login.

store.js

import { configureStore, createSlice } from '@reduxjs/toolkit'
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import { persistStore } from 'redux-persist';

const persistConfig = {
  key: 'root',
  storage: storage,
  whitelist: ['user']
};

let user = createSlice({
  name: 'user',
  initialState: {
    userId: 'anonymous',
    isLoggedIn: false
  },
  reducers: {
    changeUser(state, action) {
      state.userId = action.payload.userId;
      state.isLoggedIn = action.payload.isLoggedIn;
    }
  }
})

const persistedReducer = persistReducer(persistConfig, user.reducer);

export let { changeUser } = user.actions;

let store = configureStore({
  reducer: {
    user: persistedReducer
  }
  // persistedReducer
})

export const persistor = persistStore(store);
export default store;

Приложение.js

function App(){
  const isLoggedIn = useSelector((state) => state.user.isLoggedIn);

  return (
    <BrowserRouter>
      <RedirectToLogin />
      <Center>
        {isLoggedIn && <Sidebar userRole = {''} />}
        <Routes>
          <Route path = "/loginPage" element = {<Login />} />
          {isLoggedIn ? (
            <>
              <Route element = {<ProtectedRoute isLoggedIn = {isLoggedIn} />} />
              <Route path = "/" element = {<Editor/>}/>
              <Route path = {"/loginPage"} element = {<Login/>}/>
              <Route path = "*" element = {<NotFoundPage/>}/>
            </>
          ) : (
            <>
              <Route path = "*" element = {<Navigate to = "/loginPage" replace />} />
            </>
          )}
        </Routes>
      </Center>
    </BrowserRouter>
  )
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store, {persistor} from "./store";
import {Provider} from "react-redux";
import { PersistGate } from "redux-persist/integration/react";

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

reportWebVitals();

🤔 А знаете ли вы, что...
С помощью JavaScript можно валидировать данные на стороне клиента, что улучшает пользовательский опыт.


1
175
1

Ответ:

Решено

Проблема

Кажется, проблема связана с конфигурацией персистентности, в частности, с тем, что она вносит в белый список, и какую функцию редуктора она сохраняет:

const persistConfig = {
  key: 'root',
  storage: storage,
  whitelist: ['user']
};

При этом сохраняется ключ user редуктора, который вы сохраняете, например. user.reducer, но у редуктора среза user нет ключа user для сохранения, это просто прямая user.reducer функция.

const user = createSlice({
  name: 'user',
  initialState: {
    userId: 'anonymous',
    isLoggedIn: false
  },
  reducers: {
    changeUser(state, action) {
      state.userId = action.payload.userId;
      state.isLoggedIn = action.payload.isLoggedIn;
    }
  }
})

const persistedReducer = persistReducer(persistConfig, user.reducer);

Решение

Либо сохраните всю функцию user.reducer, например. нет белого списка в user.reducer:

import { configureStore, createSlice } from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import { persistStore } from 'redux-persist';

const user = createSlice({
  name: 'user',
  initialState: {
    userId: 'anonymous',
    isLoggedIn: false
  },
  reducers: {
    changeUser(state, action) {
      state.userId = action.payload.userId;
      state.isLoggedIn = action.payload.isLoggedIn;
    }
  }
});

export const { changeUser } = user.actions;

const persistConfig = {
  key: 'root',
  storage: storage,
};

const persistedUserReducer = persistReducer(persistConfig, user.reducer);

const store = configureStore({
  reducer: {
    user: persistedUserReducer
  }
})

export const persistor = persistStore(store);
export default store;

Или создайте функцию корневого редуктора, например. «combineReducers» и внесите в белый список состояние user.

import {
  configureStore,
  createSlice,
  combineReducers
} from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import { persistStore } from 'redux-persist';

const user = createSlice({
  name: 'user',
  initialState: {
    userId: 'anonymous',
    isLoggedIn: false
  },
  reducers: {
    changeUser(state, action) {
      state.userId = action.payload.userId;
      state.isLoggedIn = action.payload.isLoggedIn;
    }
  }
});

const persistConfig = {
  key: 'root',
  storage: storage,
  whitelist: ['user']
};

export const { changeUser } = user.actions;

const rootReducer = combineReducers({
  user: user.reducer,
});

const persistedRootReducer = persistReducer(persistConfig, rootReducer);

const store = configureStore({
  reducer: persistedRootReducer,
})

export const persistor = persistStore(store);
export default store;