Persist Redux State with redux-persist
Tags: react, redux, webdev
Published: 2021-09-01 18:31:04

When we refresh page in a web-app, the state always resets back to the initial values which in not a good thing when you try to build some large web-app like e-commerce.

We can manually do the state persistent using the native JavaScript `localStorage.setItem()` method but honestly we will have to write everything from start and we have to maintain the structure of the state.

So here the **redux-persist** comes into play, with support for _redux toolkit_, that helps us to persist the state after page refresh.

##Redux-Persist

It is a package for persisting redux state when it is connected to the store.
That's all what the package does. Pretty neat!

Without further talking, lets dive into how we actually hook it up  with _redux toolkit_ for state/store persisting. We will use a counter app for easier understanding.

###Step 1:

Install the package via `npm` or `yarn` (I will use npm here):
```
npm i redux-persist
```

###Step 2:

Add the required imports to the redux store:

```js
//store.js
import storage from 'redux-persist/lib/storage';
import { combineReducers } from 'redux';
import {
	persistReducer,
	FLUSH,
	REHYDRATE,
	PAUSE,
	PERSIST,
	PURGE,
	REGISTER,
} from 'redux-persist';
```

**redux-persist** provides different storage to persist data like local storage, session storage or async storge. We will use the local storage.

We need the `combineReducers` function to group up all the reducers into one so that we can pass it to the **redux-persist**.

**redux-persist** dispatches some functions and according to official redux-toolkit guide we need to add those to the ignore list to avoid unnecessary warnings or errors.

###Step 3:

We need to create the persist object config that will be stored to the storage:

```js
//store.js
const persistConfig = {
	key: 'counter',
	storage,
};
```

The key specifies the ID of the persist object and the storage determines the type of storage being used.

###Step 4:

Combine the reducers:

```js
//store.js
const reducers = combineReducers({ counter: counterSlice });
```

###Step 5:

Create a persistent reducer:

```js
///store.js
const persistedReducer = persistReducer(persistConfig, reducers);
```

###Step 6:

Assign the persist reducer to the reducers and extra dispatch functions to the ignore list in the middleware, at the end your store will look like this:

```js
//store.js
export default configureStore({
	reducer: persistedReducer,
	middleware: (getDefaultMiddleware) =>
		getDefaultMiddleware({
			serializableCheck: {
				ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
			},
		}),
});
```

###Step 7:

Just like _react-redux_ gives us `Provider` component that will wrap the whole app, similarly we get `PersistGate` from **redux-persist**. We need it to wrap around the whole app:

```js
//index.js
import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
//...
let persistor = persistStore(store);

ReactDOM.render(
	<React.StrictMode>
		<Provider store={store}>
			<PersistGate persistor={persistor}>
				<App />
			</PersistGate>
		</Provider>
	</React.StrictMode>,
	document.getElementById('root')
);
```

The `persistStore` will configure the store object to become compatible when we pass it to the `PersistGate` component.

###Step 8:

With all the connection done, now your react app can persist when when page changes and or the page reloads.

If we check it with _redux-logger_, we can see that it first checks with `PERSIST` action and rehydrate the store with the `REHYDRATE` action.

![redux-logger showing redux-persist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/guz1gollll1cjr4kwa8d.jpg)

##Wrapping Up

**redux-persist** is a great library for obvious reason, but it's way old and outdated, last update was at 2019 with several PR and issues at GitHub. I hope they revive the project and fix the necessary issues. Meanwhile, if you know any alternatives please let me know in the comments.