After following the official documentation on integrating Redux with Next.js app router, everything seemed to be working smoothly. However, I encountered challenges when attempting to persist the data using redux-persist
.
The official Redux docs do not provide an example for this situation. I am unsure of how to handle the fact that I am creating a Redux store per request by utilizing configureStore
within a makeStore
function (the recommended approach suggested by the official Redux documentation for using Redux with Next.js app router).
I am facing difficulties passing the makeStore
function to the persistStore
method without encountering type errors:
Argument of type '() => EnhancedStore<{ user: userInterface; } & PersistPartial, UnknownAction, Tuple<[StoreEnhancer<{ dispatch: ThunkDispatch<{ user: userInterface; } & PersistPartial, undefined, UnknownAction>; }>, StoreEnhancer]>>' is not assignable to parameter of type 'Store<any, UnknownAction, unknown>'
This is my current setup:
store.js:
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { configureStore, combineReducers } from '@reduxjs/toolkit'
import {userReducer} from "./user/userSlice"
const combinedReducers = combineReducers({
user: userReducer,
})
const persistedReducer = persistReducer(
{
key: 'root',
storage,
whitelist: ['user'],
},
combinedReducers
)
export const makeStore = () => {
return configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
})
}
export const persistor = persistStore(makeStore)
export type AppStore = ReturnType<typeof makeStore>
export type RootState = ReturnType<AppStore['getState']>
export type AppDispatch = AppStore['dispatch']
store provider:
"use client";
import { useRef } from "react";
import { Provider } from "react-redux";
import { makeStore, AppStore } from "../redux/store";
export default function StoreProvider({
children,
}: {
children: React.ReactNode;
}) {
const storeRef = useRef<AppStore>();
if (!storeRef.current) {
// Create the store instance the first time this renders
storeRef.current = makeStore();
}
return <Provider store={storeRef.current}>{children}</Provider>;
}
layout.js
import type { Metadata } from "next";
import "./globals.css";
import StoreProvider from "./StoreProvider";
export const metadata: Metadata = {
title: "App",
description: "App Desription",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<StoreProvider>{children}</StoreProvider>
</body>
</html>
);
}
How can I modify the code to achieve data persistence with Redux considering the requirement of creating the store per request?