Persisting state after page refresh in React Js

Last updated : Jul 30, 2023 12:00 AM

The simplest way to persist React state is to use the localStorage. Few third-party packages handle this for you, but they also use the localStorage under the hood. So why rely on such libraries that may not be maintained down the road? Let's implement our strategy to persist the state on page reload.

import { useState } from "react"
export const App = () => {
const [name, setName] = useState<string|undefined>(localStorage.getItem("name") || undefined)

const handleFormChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  setName(event.target.value)
  localStorage.setItem("name", event.target.value );
}

return(
      <div>
         <div>&lth3>React js window dimensions</h3></div>
         <div>Name:</div>
         &ltdiv><input value={name} onChange={(e) => handleFormChange(e)}/></div>
      </div>
   )
}
export default App

In the above example, we set the local storage with localStorage.setItem("name", event.target.value) and read the local storage with localStorage.getItem("name"). If you refresh the page, you will notice that the name will persist in the name input field. This method is ok to persist a few input values. If we want to utilize this functionality throughout the application, we need a more scalable solution.

Persist React Js state with custom hook

Below is an example of local storage using react custom hooks.

export const useLocalStorage = (name: string): Function[] => {
   const getLocalStorage = () => {
      const local = localStorage.getItem(name)
      if(local != null){
         return JSON.parse(local)
      }
      return null
   }
   const setLocalStorage = (item: Object) => {
      localStorage.setItem(name, JSON.stringify(item))
   }
   const removeLocalStorage = () => {
      return localStorage.removeItem(name)
   }
   return [getLocalStorage, setLocalStorage, removeLocalStorage]
}

The hook provides three services.
The getLocalStorage retrieves the data by calling localStorage.getItem(). The setLocalStorage sets the state to the local storage, and the removeLocalStorage simply removes the data from the local storage.

import { useEffect, useState } from "react"
import { useLocalStorage } from "./components/useLocalStorage"
export const App = () => {
   interface InputForm {
      name: string
      website: string
      contact: Contact
   }
   interface Contact {
      cell: string
      email: string
   }
   let initialForm: InputForm = {
      name: "",
      website: "",
      contact: {
         cell: "",
         email: ""
      }
   }
   const [savedForm, setSavedForm, clearLocalStorage] = useLocalStorage("inputForm")
   const [inputFormState, setInputFormState] = useState<InputForm>(savedForm() || initialForm)
   const handleFormChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      const {name, value} = event.target
      if(name === "name" || name === "website"){
         setInputFormState((prev) => {
            const newForm = {...prev}
            newForm[name] = value
            return newForm
         })
      }
      if(name === "cell" || name === "email"){
         setInputFormState((prev) => {
            let newForm:InputForm = {...prev}
            newForm.contact[name] = value
            return newForm
         })
      }
   }
   useEffect(() => {
      setSavedForm(inputFormState)
   },[setSavedForm,inputFormState])
   return(
       <div>
         <div><h3>React js Local Storage</h3></div>
         <div>Name:</div><div><input name="name" value={inputFormState?.name} onChange={(e) => handleFormChange(e)}/></div>
         <div>Website:</div><div><input name="website" value={inputFormState?.website} onChange={(e) => handleFormChange(e)}/></div>
         <div>Cell:</div><input name="cell" value={inputFormState?.contact?.cell} onChange={(e) => handleFormChange(e)}/></div>
         <div>Email:</div><input name="email" value={inputFormState?.contact?.email} onChange={(e) => handleFormChange(e)}/></div>
         <div><button onClick={()=>clearLocalStorage()}>Clear Cache</button></div>
      </div>
   )
}
export default App
Figure 1: How to persist state values after page refresh in React JS
Figure 1: How to persist state values after page refresh in React JS

Note that we initialize the inputFormState as
const [inputFormState, setInputFormState] = useState(savedForm() || initialForm).
This handles the initial page load without any local storage values present. If the local storage is not yet set, then the initial state is used to create the inputFormState. Then we call setSavedForm(inputFormState) in the useEffect hook to persist any input values to the form.

Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...