Persisting State like a Pro: Redux-Persist in React/Next

Vignesh Murugan
4 min readMay 5, 2023

--

Have you ever tried refreshing your page after using the useState hook or REDUX TOOLKIT for state management, then you might know that your state values will get reset to default. REDUX PERSIST comes here for rescuing our state values.

REDUX PERSIST is an npm library that helps to persist our state values of the REDUX store in persistent storage, eg. local storage. On each app launch/ refresh it retrieves the persisted state.

An example use-case is, imagine a user logged in to your e-commerce store and added a product to his cart, but mistakenly he refreshed/ reloaded the page then he’ll either get logged-out or the item he added to the cart will get removed. To avoid such a situation we use REDUX PERSIST.

Okay enough of the jingle bingle storytime, let’s get to the coding part. If you have not used REDUX TOOLKIT before check out this article first since we’ll need REDUX TOOLKIT in our project as the primary criteria for using REDUX PERSIST.

RTK article link: https://medium.com/@web3vicky/boost-your-productivity-with-redux-toolkit-rtk-in-react-js-next-js-5edab76e8aba

Okay let’s start 🥁

First things First, I hope you know how to create a React/ Next project so I’m skipping those steps and getting directly to the point. Here I used NEXT JS 13 application since CRA is officially dead.

1.) Install the necessary dependencies

npm install redux-persist redux-thunk

2.) In your ‘store.js’ file import these libraries

//store.js

import { persistReducer, persistStore } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { combineReducers } from "@reduxjs/toolkit";
import thunk from "redux-thunk";
  • ‘persitReducer’ is basically a function that takes in a Redux reducer and returns a new reducer that is capable of persisting the state.
  • ‘persistStore’ is a function that takes in a Redux store and returns a promise that resolves with the persisted version of the store.
  • ‘storage’ is an object which is used to set the storage for our persisted state vaules.
  • ‘combinedReucers’ is a function that is used to combine all our slice reducers into a single object.
  • ‘thunk’ acts as a middleware that will return you a function instead of an object while calling through the action creators

3.) Now create a variable called ‘reducers’ and use the ‘combinedReducer’ function to add all reducers under a single object.

// store.js

const reducers = combineReducers({
user: userSlice,
data: dataSlice,
});

4.) Now create an object with variable ‘persistConfig’ and add the cofiguration required for our Redux-persist.

//store.js

const persistConfig = {
key: 'root',
whitelist: ['user'],
blcaklist: ['data'],
storage,
}
  • key: ‘root’ is used to identify the persisted state in the storage engine. This means that all persisted states will be stored under a single key called ‘root’ by default.
  • ‘whitelist’ is used to define the array of slices whose states you want to be persisted, while items in ‘blacklist’ won’t be persisted.
  • ‘storage’ variable is used to define the storage used by redux-persist, either local or session storage API.

5.) Now create a variable ‘persistedReducer’ and use ‘persistReducer’ function to which takes persistConfig and reducers as the parameters.

Then in the default ‘store’ variable which consists of a reducer, update the code with assigning reducer and middleware to the respective values.

Use the ‘persistStore ’ function with ‘store ’ as a parameter and assign it to a variable ‘persistor’.

//store.js

const persistedReducer = persistReducer(persistConfig, reducers);

const store = configureStore({
reducer: persistedReducer,
middleware: [thunk],
})

export const persistor = persistStore(store);

6.) The final code in ‘store.js’ will look like below:

// store.js

import userSlice from "./userSlice";
import dataSlice from "./dataSlice";
import { configureStore } from "@reduxjs/toolkit";
import { persistReducer, persistStore } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { combineReducers } from "@reduxjs/toolkit";
import thunk from "redux-thunk";

const reducers = combineReducers({
user: userSlice,
data: dataSlice,
});

const persistConfig = {
key: 'root',
whitelist: ['user'],
blcaklist: ['data'],
storage,
}

const persistedReducer = persistReducer(persistConfig, reducers);

const store = configureStore({
reducer: persistedReducer,
middleware: [thunk],
})

export const persistor = persistStore(store);

export default store;

7.) Finally in our ‘_app.js’ for NEXT or ‘App.js’ for REACT, we need to import our ‘store’ and ‘persistor’. Then we need to wrap the ‘PersistGate’ on top of our APP component and next to the ‘Provider ’ of ‘React-Redux’ and pass our persistor to it.

// _app.js

import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import store from '../store/store';
import { persistor } from '../store/store';


export default function App({ Component, pageProps }) {

return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Component {...pageProps} />
</PersistGate>
</Provider>
)}

That’s it you have successfully implemented the REDUCX PERSIST to your react/next project along with Redux Toolkit (RTK). 🧙‍♂️✨

Now hit that reload button harder 🧈, again and again, to find your state values being persisted and remaining the same.

Is it useful?! Give this a clap and share it with your friends, do follow for more content.

See you in the next article, Happy Coding! 👨‍💻❤

--

--