How to persist Redux state in local Storage without any external library?
Last Updated :
23 Jul, 2025
Redux as per the official documentation is a predictable state container for JavaScript apps. In simple words, it is a state management library, with the help of Redux managing the state of components becomes very easy. We can manage the state of the app by creating a global state known as a store.
The idea to use Redux may be fine for a complex react app but this state is not persistable throughout. It means that once you reload the browser the state of the app changes and reaches its default state. Persisting the data of such react apps is very easy. We will be using local storage to store the current state of the React app and persist the data even on reloads.
Creating React Application And Installing Module:
Step 1: Create a React application using the following command:
npx create-react-app myapp
Step 2: After creating your project folder i.e. myapp, move to it using the following command:
cd myapp
Step 3: After creating the ReactJS application, Install the required modules using the following command:
npm install redux
npm install react-redux
Project Structure: It will look like the following.
Project StructureExample: We will create a simple shopping cart application through which we will persist data to our local storage.
Filename- App.js This is the App component of our React app. All the dependencies that are required for a typical react application are imported. The provider function is imported from react-redux. This will act as a wrapping component for our App, to this wrapping component we will pass the store. The store is basically a global state of our application.
JavaScript
import React from "react";
import { Provider } from 'react-redux';
import CartContainer from "./components/CartContainer";
// Store
import { store } from './store';
import { saveState } from './localStorage';
store.subscribe(() => {
saveState({
cart: store.getState().cart,
total: store.getState().total,
amount: store.getState().amount
});
});
// Items
const cartItems = [
{
id: 1,
title: "Samsung",
price: 799.99,
img:
"shorturl.at/ajkq9",
amount: 1
},
{
id: 2,
title: "Google pixel Max",
price: 399.99,
img:
"shorturl.at/ajkq9",
amount: 1
},
{
id: 3,
title: "Xiaomi",
price: 999.99,
img:
"shorturl.at/ajkq9",
amount: 1
}
];
function App() {
return (
<Provider store={store}>
<CartContainer cart={cartItems} />
</Provider>
);
}
export default App;
Filename- store.js In this file, the basic store set up is done using redux. The store is initialized and the state is being persisted to local storage. The redux store contains total, amount, and cart items. This store's state will be later saved in the local storage.
JavaScript
import reducer from './reducer';
import { createStore } from 'redux';
import { loadState } from './localStorage';
const cartItems = [
{
id: 1,
title: "Samsung",
price: 799.99,
img:
"shorturl.at/ajkq9",
amount: 1
},
{
id: 2,
title: "Google pixel Max",
price: 399.99,
img:
"shorturl.at/ajkq9",
amount: 1
},
{
id: 3,
title: "Xiaomi",
price: 999.99,
img:
"shorturl.at/ajkq9",
amount: 1
}
];
const persistedState = loadState();
const initialStore = {
cart: cartItems,
amount: 0,
total: 0,
persistedState
}
export const store = createStore(reducer, persistedState);
Filename: reducer.js This file contains the reducer function. As per the action dispatched through the UI, the corresponding functionality takes place. Mainly our reducer will be dealing with 5 basic operations of our app namely:
- The DECREASE action decreases the quantity of the items in our cart.
- The INCREASE action increases the quantity of the items in our cart.
- The REMOVE action removes an item from the cart.
- The CLEAR_CART action basically clears the entire cart.
- The GET_TOTALS action gets the sum of all the items in our cart.
Note: One important thing to remember is that do not mutate the state of the app while using Redux.
JavaScript
import {
INCREASE,
DECREASE,
REMOVE,
CLEAR_CART,
GET_TOTALS,
} from './actions';
function reducer(state, action) {
if (action.type === DECREASE) {
return {
...state, cart: state.cart.map((item) => {
if (item.id === action.payload.id) {
if (item.amount === 0) {
return item;
} else {
item.amount--;
}
}
return item;
})
}
}
if (action.type === INCREASE) {
return {
...state, cart: state.cart.map((item) => {
if (item.id === action.payload.id) {
item.amount++;
}
return item;
})
}
}
if (action.type === CLEAR_CART) {
return { ...state, cart: [] };
}
if (action.type === REMOVE) {
return {...state, cart: state.cart.filter(item => item.id !== action.payload.id)}
}
if (action.type === GET_TOTALS) {
let { total, amount } = state.cart.reduce((cartTotal, cartItem) => {
const { price, amount } = cartItem;
cartTotal.amount += amount;
cartTotal.total += Math.floor(amount * price);
return cartTotal;
}, { amount: 0, total: 0 });
return { ...state, total, amount };
}
return state;
}
export default reducer;
Filename: CartItem.js This file contains the code for the cartItem component. It is in this file that different methods are dispatched. The function mapDispatchToProps include three actions DECREASE, INCREASE, REMOVE.
JavaScript
import React from "react";
import { connect } from 'react-redux';
import { DECREASE, INCREASE, REMOVE } from '../actions';
const CartItem = ({ title, price, img, amount, increase, decrease, remove }) => {
return (
<div className="cart-item">
<img src={img} alt={img} />
<div>
<h4>{title}</h4>
<h4 className="item-price">${price}</h4>
</div>
<div>
{/* increase amount */}
<button className="amount-btn"
onClick={() => increase()}>
<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M10.707 7.05L10 6.343 4.343 12l1.414 1.414L10 9.172l4.243 4.242L15.657 12z"
/>
</svg>
</button>
{/* amount */}
<p className="amount">{amount}</p>
{/* decrease amount */}
<button className="amount-btn"
onClick={() => decrease()} >
<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"
/>
</svg>
</button>
</div>
</div>
);
};
const mapDispatchToProps = (dispatch, ownProps) => {
const { id, amount } = ownProps;
return {
increase: () => dispatch({ type: INCREASE, payload: { id } }),
decrease: () => dispatch({ type: DECREASE, payload: { id } }),
remove: () => dispatch({ type: REMOVE, payload: { id, amount } })
}
}
export default connect(null, mapDispatchToProps)(CartItem);
Filename- CartContainer.js This file imports the CartItem component and passes them the props that are needed. Here we connect mapStateToProps and mapDispatchToProps and then pass CartContainer to it.
JavaScript
import React from "react";
import CartItem from './CartItem';
import { connect } from 'react-redux';
import { CLEAR_CART, GET_TOTALS } from '../actions';
const CartContainer = ({ cart = [], total, remove, getTotal }) => {
React.useEffect(() => {
getTotal();
})
if (cart.length === 0) {
return (
<section className="cart">
<header>
<h2>your bag</h2>
<h4 className="empty-cart">
is currently empty
</h4>
</header>
</section>
);
}
return (
<section className="cart">
{/* cart header */}
<header>
<h2>your bag</h2>
</header>
{/* cart items */}
<article>
{cart.map((item) => {
return <CartItem key={item.id} {...item} />
})}
</article>
{/* cart footer */}
<footer>
<hr />
<div className="cart-total">
<h4>
total <span>${total}</span>
</h4>
</div>
<button className="btn clear-btn"
onClick={() => remove()} >clear cart</button>
</footer>
</section>
);
};
function mapStateToProps(store) {
const { cart, total } = store;
return { cart: cart, total: total };
}
function mapDispatchToProps(dispatch) {
return {
remove: () => dispatch({ type: CLEAR_CART }),
getTotal: () => dispatch({ type: GET_TOTALS })
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CartContainer);
Filename- localStorage.js Now we will be adding the localStorage.js file. The method of persisting of data requires only four simple steps:
Step 1: Create a file named localStorage.js in the root folder typically in the src folder of your react app. In this file, we will be adding two methods one to load state from the local storage and the other method to save state to the local storage. The code for loadState method is as follows:
JavaScript
export const loadState = () => {
try {
const serialState = localStorage.getItem('appState');
if (serialState === null) {
return undefined;
}
return JSON.parse(serialState);
} catch (err) {
return undefined;
}
};
In the local storage, data is stored in the form of key-value pairs. Here the key is 'appState' and the value will be the actual state of the app.
Step 2: Code for saveState method is as follows:
JavaScript
export const saveState = (state) => {
try {
const serialState = JSON.stringify(state);
localStorage.setItem('appState', serialState);
} catch(err) {
console.log(err);
}
};
Step 3: Now in the store.js file import the loadState method from the localStorage.js file and get its value in the persistedState constant. Now as an object put this persistedState constant with the actual state of your app and export it by passing it to the store.
Filename- store.js
JavaScript
import reducer from './reducer';
import {createStore} from 'redux';
import {loadState} from './localStorage';
const persistedState = loadState();
const initialStore={
/* state of your app */
cart:cartItems,
amount:0,
total:0,
persistedState
}
export const store=createStore(reducer,persistedState);
Step 4: This is the most important step as this involves saving the state to the local storage of the browser. Now in the App.js component import the store from the store.js file and saveState() method from the localStorage.js file. Now save the state of the app by calling the subscribe function from the store.
Filename- App.js
JavaScript
import {store} from './store';
import {saveState} from './localStorage';
store.subscribe(() => {
saveState({
/* example state */
cart:store.getState().cart,
total:store.getState().total,
amount: store.getState().amount
});
});
Now just pass this store to the Provider component in the App component and the data will become persistent in the local storage.
Output: You can check the state by opening developer tools on chrome and then navigating to Application then to Storage than to local storage. In the local storage, you'll see the key named appState. This is the place where the entire data is stored.
Similar Reads
React Tutorial React is a powerful JavaScript library for building fast, scalable front-end applications. Created by Facebook, it's known for its component-based structure, single-page applications (SPAs), and virtual DOM,enabling efficient UI updates and a seamless user experience.Note: The latest stable version
7 min read
React Fundamentals
React IntroductionReactJS is a component-based JavaScript library used to build dynamic and interactive user interfaces. It simplifies the creation of single-page applications (SPAs) with a focus on performance and maintainability. "Hello, World!" Program in ReactJavaScriptimport React from 'react'; function App() {
6 min read
React Environment SetupTo run any React application, we need to first setup a ReactJS Development Environment. In this article, we will show you a step-by-step guide to installing and configuring a working React development environment.Pre-requisite:We must have Nodejs installed on our PC. So, the very first step will be
3 min read
React JS ReactDOMReactDOM is a core React package that provides DOM-specific methods to interact with and manipulate the Document Object Model (DOM), enabling efficient rendering and management of web page elements. ReactDOM is used for: Rendering Components: Displays React components in the DOM.DOM Manipulation: Al
2 min read
React JSXJSX stands for JavaScript XML, and it is a special syntax used in React to simplify building user interfaces. JSX allows you to write HTML-like code directly inside JavaScript, enabling you to create UI components more efficiently. Although JSX looks like regular HTML, itâs actually a syntax extensi
5 min read
ReactJS Rendering ElementsIn this article we will learn about rendering elements in ReactJS, updating the rendered elements and will also discuss about how efficiently the elements are rendered.What are React Elements?React elements are the smallest building blocks of a React application. They are different from DOM elements
3 min read
React ListsIn lists, React makes it easier to render multiple elements dynamically from arrays or objects, ensuring efficient and reusable code. Since nearly 85% of React projects involve displaying data collectionsâlike user profiles, product catalogs, or tasksâunderstanding how to work with lists.To render a
4 min read
React FormsForms are an essential part of any application used for collecting user data, processing payments, or handling authentication. React Forms are the components used to collect and manage the user inputs. These components include the input elements like text field, check box, date input, dropdowns etc.
5 min read
ReactJS KeysA key serves as a unique identifier in React, helping to track which items in a list have changed, been updated, or removed. It is particularly useful when dynamically creating components or when users modify the list. When rendering a list, you need to assign a unique key prop to each element in th
4 min read
Components in React
React Lifecycle In React, the lifecycle refers to the various stages a component goes through. These stages allow developers to run specific code at key moments, such as when the component is created, updated, or removed. By understanding the React lifecycle, you can better manage resources, side effects, and perfo
7 min read
React Hooks
Routing in React
Advanced React Concepts
React Projects