How to persist React states after a refresh?! ( Part 1 )

Adel Benyahia
3 min readOct 22, 2022
Persist React State in localStorage

React is a popular library that makes developer life easier. It provides a variety of powerful APIs to manage all our apps.

To store and manage variables in react, we will use a hook called useState

When using useState we store variable value in a state and manage it with a setState function:

Const [counter, setCounter]= useState (0)

In this example we declared a state with a name “counter" and a default value of 0.

The value of this state can be managed with “setCounter()".

Now a full example

import React, { useEffect, useState } from “react”;export default function App() {
const [count, setCount] = useState(0);
const increaseCount = () => {
return setCount(count + 1);
}
const decreaseCount = () => {
return setCount(count — 1)
}
return (
<div>
<h1> Count {count} </h1>
<button onClick={increaseCount}>+</button>
<button onClick={decreaseCount}>-</button>
</div>
);
}

In this example we have a state with a name “count", the value of this count state will be increased and decreased by clicking two buttons (using the “setCount" function).

All working good 👍… wait try to refresh the page, the value of count return to 0 (it’s default value), that’s because the state is only saved in the memory and will not persist for a refresh or a reload of the application.

The solution is very easy for that.

First solution: using localStorage:

localStorage is a browser API that allows developers to store data and later read it, it’s basically a database inside of your browser.

With localStorage, we can store string variables with a key name, for more complex variables like objects and arrays we can use JSON.stringify() before and JSON.parse() after.

Add this code to the example below

useEffect(() => {setCount(JSON.parse(window.localStorage.getItem(’count’)));
}, []);
useEffect(() => {
window.localStorage.setItem(’count’, count);
}, [count]);

We are using useEffect hook: useEffect(callback, [dependencies]);

useEffect() hook accepts 2 arguments:

  • callback is the function containing the side-effect logic. callback is executed right after changes were being pushed to DOM.
  • dependencies is an optional array of dependencies; When the dependencies array is empty, useEffect will run only once after the component renders.
  • In the first useEffect, we stored the counter to the value stored in the local storage with the key name “count" using the function window.localStorage.getItem()
  • In the second useEffect we are passing the state “count" as a dependency, this means that every time the value of count changes, the callback function in this useEffect will be executed, in this case: window.localStorage.setItem(), with will save the value of the state to localSorage under the key name “count”.

Try it. Change the value of count by clicking the two buttons, then refresh the page and check if the value of the counter persists.

We will now update the first useEffect and add some logics

useEffect(() => {const value = window.localStorage.getItem(“count”);const valueParse = JSON.parse(value) ? JSON.parse(value) : 0;setCount(valueParse);}, []);
  • first we get the value with the function localStorage.getItem().
  • then we try to parse value using JSON.parse()
  • if the operation succeed then we passe the result to valueParse else we passe the default value in our case : 0.

Check out your DevTools

working example on codesandboxe

Learn more

--

--

Adel Benyahia

Web application developer (HTML │ CSS │ JS | ReactJS | NextJS | NestJS | MERN)