Integrating Redux and NextJS

NextJS provides an out-of-the-box development experience for building apps complete with server side rendering, routing and performance optimizations. Integrating Redux raises a couple of questions:

  • Where do we initialize the store?
  • How do we define initial state?
  • How do we use the store in components?
  • How do we handle state when navigating?

This article aims to be a quick and dirty breakdown of the NextJS + Redux example here, answering these questions along the way.

It’s a good idea to make sure you understand the following concepts before trying to piece everything together:

  1. Redux fundamentals | https://redux.js.org/tutorials/essentials/part-1-overview-concepts
  2. NextJS Pages | https://nextjs.org/docs/basic-features/pages
  3. NextJS SSR, SSG | https://nextjs.org/docs/basic-features/data-fetching
  4. NextJS Routing | https://nextjs.org/docs/routing/introduction

Setting up

npx create-next-app --example with-redux my-app

This will set up the Redux example into the my-app directory, located wherever you execute the command. cd into the directory and run npm install to finalize setup.

Store initialization

  • If rendered server side, it will always initialize a new store to avoid injecting user specific data into pre-rendered pages.
  • If rendered client side, it will create a store if one doesn’t exist or return an existing store² (it could also return a new store with previously existing state³, this will be covered later).

In both cases, it’s called by a hook at the root of the application from a custom App component⁴. This ensures it’s called whenever a page renders, enabling us to

  • Initialize the store with page specific state
  • Pass the store to the rest of the application
  • Handle navigating from page to page

[1] New store when rendering serverside | [2] Existing store assignment | [3] New store with previous state| [4] useStore hook

Initial state

Page specific initial state is defined using NextJS’s data fetching methods, e.g. getServerSideProps. With them we inject data that is appropriate for being fetched server side, such as auth state or data from requests requiring secrets.

Depending on your requirements, this can be done for pages rendered dynamically on each request² (SSR) or pre-rendered pages served from cache³(SSG).

If no initial page state is defined via NextJS’s data fetching methods, the app will default to initializing with the hardcoded state⁴.

[1] Default state | [2] SSR Initial state | [3] SSG initial state | [4] Default state init

Using the store in components

The stores are then referenced using useSelector and useDispatch to access state and dispatch actions².

[1] Provider usage | [2] State reference and action dispatch

Navigating with state

The hook mentioned previously handles this, if our app sees the page specific initial state has changed when a page re-renders¹, it will merge the new state into the existing one and re-initialize the store².

Note that this approach will create a new instance of the store, meaning if you’re debugging the page with e.g. redux dev tools it will show the old store as unchanged and you will have to select the new store manually.

[1] useMemo rerunning store init on initial state change | [2] New store with previous state

Conclusion

  • Redux toolkit usage: redux-toolkit is a library for simplifying your redux logic, be it providing good defaults for store initialization, cutting down on the boilerplate with state slices or introducing “mutable” updates to your state with the help of immer. Carefully introducing redux-toolkit into your app early could ensure it scales well into the future.
  • Better page navigation state handling: the current example rebuilds the store whenever the initial state of the page changes. While this is functional, it does create a new instance of the store which complicates logic that depends on references to the original store, like debugging via tools a la redux-dev-tools. A better approach would hydrate the existing store with new state without modifying the reference to the store e.g. via an action.

This is my first article. Hopefully it was useful and things are a little clearer than they were when you first started reading :)

Cobbling the web together, 1 character at a time.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store