Search code examples
javascriptreactjsnext.jsreduxredux-toolkit

NextJs app router with redux-toolkit for SSR not setting to initial state after navigation


I have a simple project using NextJs with the app router, and I am also using redux/redux-toolkit for state management, but I am having some small issues.

When I populate the redux state on "page1", and the user navigates to "page2", the data that has been fetched on "page1" still exists on the redux state even though I did not fetch those data on the "page2". The same thing when the user goes back to "page1" from "page2", the data that I fetch on the "page2" still exists in the redux state.

To give you an idea of what I mean, I created this simple CodeSandbox where you can check. https://codesandbox.io/p/devbox/nextjs-redux-toolkit-z5x2tw

I am using the <a> tag for navigations because the idea is to fetch the data every time the user navigates to a different page. When the user navigates to "Pokemons", we populate the pokemons state, and when the user navigates to "Pokemon" (without 's'), we only fetch and populate the pokemon (without 's') state.

We are expecting that the redux state should return to the initial state every time the user navigates to a different page since we don't use a persistent state library or save the state to any storage. I believe this should be the default behavior of redux/redux-toolkit, or am I missing something?


Solution

  • I can confirm that the NextJs state is persistent on every user navigation. If you are using createContext, useContext hooks, this can be solved by import { unstable_noStore } from 'next/cache'; documentation here, though, this doesn't work with Redux. Even using templates.(js/tsx) documentation here, the store still becomes persistent.

    To solve this, I add a revertAll action on every slice then call it on every page to reset the store on every navigation. I am not sure if this is the correct approach but this solves my concern. Sample code below:

    redux/slice/global.ts
    
    export const global = createSlice({
      name: "global",
      initialState,
      extraReducers(builder: any) {
        builder.addCase(revertAll, () => initialState);
        ...
      },
      reducers: {
        ...
      },
    });
    

    Then calling this function to revert the store every time the user navigates

    app/page.tsx
    
    async function getData() {
      reduxStore.dispatch(revertAll());
      ...
    }
    
    export default async function Page() {
      await getData();
      ...
      }
    

    I hope this helps someone having the same concern. Thank you.