skip to Main Content

I’m about to setup a new project using nextjs using the new app router, I could set redux toolkit up using a provider based on official example in nextjs repository : https://github.com/vercel/next.js/tree/canary/examples/with-redux
but the problem is when I add redux-persist:

"use client";

import { PersistGate } from "redux-persist/integration/react";
/* Core */
import { Provider } from "react-redux";

/* Instruments */
import { persistor, reduxStore } from "@/lib/redux";

export const Providers = ({ children }) => {
  return (
    <Provider store={reduxStore}>
      <PersistGate persistor={persistor}>
        {children}
      </PersistGate>
    </Provider>
  );
};

also tried importing PersistGate using dynamic import:

"use client";

import dynamic from "next/dynamic";

const PersistGateComponent = dynamic(
  () =>
    import("redux-persist/integration/react").then((mod) => mod.PersistGate),
  {
    ssr: false,
  }
);

const SSROutset = ({ children, persistor }) => {
  if (typeof window !== "undefined") {
    return (
      <PersistGateComponent persistor={persistor}>
        {children}
      </PersistGateComponent>
    );
  }

  // You can create a visually hidden component to avoid layout flashes and also maintain SEO content
  // see Chakra for an example of one https://chakra-ui.com/docs/components/visually-hidden
  return (
    <span
      style={{
        border: "0",
        clip: "rect(0, 0, 0, 0)",
        height: "1px",
        width: "1px",
        margin: "-1px",
        padding: "0",
        overflow: "hidden",
        whiteSpace: "nowrap",
        position: "absolute",
      }}
    >
      {children}
    </span>
  );
};

export default SSROutset

and:

"use client";

/* Core */
import { Provider } from "react-redux";

/* Instruments */
import { persistor, reduxStore } from "@/lib/redux";
import SSROutset from "./redux/SSROutset";

export const Providers = ({ children }) => {
  return (
    <Provider store={reduxStore}>
      <SSROutset persistor={persistor}>
        {children}
      </SSROutset>
    </Provider>
  );
};

still getting following errors:

Hydration failed because the initial UI does not match what was rendered on the server.

2

Answers


  1. I solved this problem with useEffect

    const { list } = useAppSelector(state => state.example);
    
    const [isMounted, setIsMounted] = useState(false);
    
    useEffect(() => {
      setIsMounted(true);
    }, []);
    
    return (
      <div>
         {isMounted && list.length > 0 && ( ... )}
      </div>
    )
    
    Login or Signup to reply.
  2. I have work around this problem
    the store initial

    import {
      addToCartMiddleware,
      updateCartMiddleware,
      deleteCartMiddleware,
    } from "./slices/checkout/middleware";
    import CheckoutLineReducer from "./slices/checkout/Line.Slice";
    
    let store;
    
    const rootReducer = combineReducers({
      notification: NotificationReducer,
    
    });
    
    const middlewares = [
      addToCartMiddleware,
      updateCartMiddleware,
      deleteCartMiddleware,
      thunk,
    ];
    
    const persistConfig = {
      key: "primary",
      storage,
      whitelist: ["auth", "checkout"],
    };
    
    const persistedReducer = persistReducer(persistConfig, rootReducer);
    
    function makeStore() {
      return configureStore({
        reducer: persistedReducer,
        devTools: process.env.NODE_ENV !== "production",
        middleware: middlewares,
      });
    }
    
    export const initializeStore = (preloadedState) => {
      let _store = store ?? makeStore();
    
      // For SSG and SSR always create a new store
      if (typeof window === "undefined") return _store;
    
      // Create the store once in the client
      if (!store) store = _store;
    
      return _store;
    };
    
    export function useStore() {
      const store = useMemo(() => initializeStore(), []);
      return store;
    }
    
    export default makeStore;

    and after that I make Provider component to wrap the project in Layout

    "use client";
    import { Provider } from "react-redux";
    import { PersistGate } from "redux-persist/integration/react";
    import { persistStore } from "redux-persist";
    import { useStore } from "@/lib/redux/store";
    
    const ProviderWrapper = ({ children }) => {
      const store = useStore();
      let persistor;
    
      if (store) {
        persistor = persistStore(store, {}, function () {
          persistor.persist();
        });
      }
    
      return (
        <Provider store={store}>
          <PersistGate loading={<p>loading</p>} persistor={persistor} />
          {children}
        </Provider>
      );
    };
    
    export default ProviderWrapper;

    the persist store working but it makes alot of action in the
    persist/PERSIST
    persist/REYHIDRATION

    note: in Provider I put children out of PersistCate because when you add it inside the persist gate all the application will be client side

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search