Persisting state after page refresh in React Js

Last updated : July 17, 2022

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>React js window dimensions</h3></div>
    <div>Name:<div><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
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<InputForm>(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.

L Raney
By: L Raney
Lance is a software engineer with over 15 years of experience in full-stack software development.
Read more...

Comments are disabled

No Comments