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><h3>React js window dimensions</h3></div>
<div>Name:</div>
<div><input value={name} onChange={(e) => handleFormChange(e)}/></div>
</div>
)
}
export default App
In the above example, we set the local storage with
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
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
Note that we initialize the inputFormState as
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