DEV Community

Cover image for Simplest way to persist redux state to localStorage
Igor Petrovic
Igor Petrovic

Posted on

Simplest way to persist redux state to localStorage

For a next.js web app, I needed to persist the redux state to the browser's localStorage. In this article, I assume you already know how to setup redux in a next.js app.

Why should I persist the state ?

In this project, there is no database or user session. But still, the user should be able to save and resume its work on each visit to the app.

Demo app

It's a simple ToDo app to demonstrate this technic. You can check it on here
Todo app stackblitz

Let's see the code

What we need first is two function to serialize and deserialize redux state.


const KEY = "redux";
export function loadState() {
  try {
    const serializedState = localStorage.getItem(KEY);
    if (!serializedState) return undefined;
    return JSON.parse(serializedState);
  } catch (e) {
    return undefined;

export async function saveState(state: any) {
  try {
    const serializedState = JSON.stringify(state);
    localStorage.setItem(KEY, serializedState);
  } catch (e) {
    // Ignore
Enter fullscreen mode Exit fullscreen mode

Then in pages/_app.tsx we subscribe to the store so we can save it each time a change happens.


import "tailwindcss/tailwind.css";
import type { AppProps } from "next/app";
import { Provider } from "react-redux";
import { saveState } from "app/browser-storage";
import { debounce } from "debounce";
import { store } from "app/store";

// here we subscribe to the store changes
  // we use debounce to save the state once each 800ms
  // for better performances in case multiple changes occur in a short time
  debounce(() => {
  }, 800)

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Provider store={store}>
      <Component {...pageProps} />
export default MyApp;
Enter fullscreen mode Exit fullscreen mode

The last part is how to restore the saved state when the user comes back. This is done in the store configuration.
We use reduxjs/toolkit configureStore and it's preloadedState configuration property.


import { configureStore } from "@reduxjs/toolkit";
import { combineReducers } from "redux";

import todosReducer from "./feature/todo";
import { loadState } from "./browser-storage";

const reducers = combineReducers({
  todos: todosReducer,

export const store = configureStore({
  devTools: true,
  reducer: reducers,
  // here we restore the previously persisted state
  preloadedState: loadState(),

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;
Enter fullscreen mode Exit fullscreen mode


  • Using localStorage to persist app's state could impact its performance especially if you have a large state.
  • localStorage is not a bulletproof solution. If the user resets its browser cache app state is lost.


The code is available here github


No relative imports

You probably noticed that my imports don't use relative paths like ../app/store but app/store this is done by configuring your tsconfig.json with compilerOptions baseUrl.

  "compilerOptions": {
    "baseUrl": "."
Enter fullscreen mode Exit fullscreen mode

Top comments (5)

ph1109ji profile image
Phuoc the Pearl is always very helpful indeed.
But I have a question, can I only save to localStorage ONE STATE SLICE rather than an entire redux store? I think storing an entire redux store will cost much perfomance whereas I only need to store one state slice.

cyberwombat profile image

Yes you can save only a slice such as: saveState(store.getState().mySlice

nirmalsankalana profile image

This code is super simple and super useful. I used this in my project instead of using redux-persist because it gave me some errors. Thanks a lot

deepakvishwakarmahh profile image
Deepak Vishwakarma

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

ahmadammmoura profile image

did you find a solution for that ?