reduxredux-toolkitredux-persistnext.js13

how to configure and persist redux toolkit in nextjs 13


I'm having trouble using the reduxjs toolkit to persist redux with nextjs 13. The code I'm using below fails to build sync storage, according to the nextjs console. reverting to noop storage. Can anyone help to me how to use the nextjs and reduxjs toolkit to persist a redux?

Here is the actual console message error: redux-persist failed to create sync storage. falling back to noop storage

Here is what I've done:

I have this in my store.js

import { configureStore } from "@reduxjs/toolkit";
import authenticateSlice from "./slices/authenticateSlice";
import { persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import { encryptTransform } from "redux-persist-transform-encrypt";
import { combineReducers } from "redux";
import thunk from "redux-thunk";

const reducers = combineReducers({
  auth: authenticateSlice.reducer,
});

let transforms = null;

if (process.env.NODE_ENV === "production") {
  const encrypt = encryptTransform({
    secretKey: process.env.NEXT_PUBLIC_REDUX_SECRET,
    onError: function (error) {
      // Handle the error.
    },
  });
  transforms = [encrypt];
}

const persistConfig = {
  key: "root",
  storage,
  transforms,
};

const persistedReducer = persistReducer(persistConfig, reducers);

const store = configureStore({
  reducer: persistedReducer,
  middleware: [thunk],
});

export default store;

then I wrapped it in my _app.js since I am with nextjs 13:

import "@/styles/globals.css";
import Head from "next/head";
import Template from "template/index";
import React from "react";
import store from "next-redux/store";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { persistStore } from "redux-persist";
import LinearProgress from "@mui/material/LinearProgress";
import ReactDOM from "react-dom";

let persistor = persistStore(store);

const App = ({ Component, pageProps }) => {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Provider store={store}>
        <PersistGate persistor={persistor} loading={<LinearProgress />}>
          <Template>
            <Component {...pageProps} />
          </Template>
        </PersistGate>
      </Provider>
    </>
  );
};

export default React.memo(App);

Solution

  • Since you are using v6 of redux-persist you need to do the following:

    First add the AsyncStorage package as follows:

    yarn add @react-native-async-storage/async-storage
    

    then,

    import AsyncStorage from '@react-native-async-storage/async-storage';
    const persistConfig = {
      //...
      storage: AsyncStorage,
    }
    

    Please don't forget to remove the below line

    import storage from "redux-persist/lib/storage";
    

    Reference link - Release notes for Redux-Persist v6

    UPDATE

    I guess the error you are facing is because you cannot create the local storage in Node.js. Hence you will need to import

    import createWebStorage from "redux-persist/lib/storage/createWebStorage";
    

    and add a check as follows:

    const storage = typeof window !== "undefined" ? createWebStorage("local") : createNoopStorage();
    

    Here you will find the detailed explanation.