useLocalStorage (React)

Save to localStorage whenever state changes and read form it for the first render.

typescriptjavascript
import type { Dispatch, SetStateAction } from 'react'
import { useCallback, useEffect, useState } from 'react'
const useLocalStorage = <T>(
key: string,
initialValue: T
): [get: T, set: Dispatch<SetStateAction<T>>, clear: () => void] => {
const [state, setState] = useState<T>(() => {
const cached = localStorage.getItem(key)
if (!cached) return initialValue
try {
return JSON.parse(cached) as T
} catch (err) {
return initialValue
}
})
useEffect(() => {
localStorage.setItem(key, JSON.stringify(state))
}, [state, key])
const clearState = useCallback(() => {
setState(initialValue)
}, [initialValue])
return [state, setState, clearState]
}

Info

  • We use useCallback for the clearState function to prevent unnecessary re-renders if you use the clearState function inside a useEffect or useCallback and list it in the dependency array.

Warning

  • This version of the hook with only work client-side and will throw an error you server-render a component using the hook
  • You should only run the hook once per key at a time - the hook doesn't handle changes when another instance of the hook updates the matching key in localStorage. If you do want to handle that, check out useSyncedLocalStorage

Usage

tsxjsx
const Example = () => {
const [input, setInput] = useLocalStorage('example:input', '')
return (
<>
<input value={input} onChange={e => setInput(e.target.value)} />
</>
)
}

Demo

Watch the value for the example:input key in the Application > Local Storage section in your devtools as you type in the input. If you're on mobile, enter some text into the input, and reload the page - when you do, you'll see the same text that you entered pre-filled.

Created 03/26/21Updated 03/18/23
Found a mistake, or want to suggest an improvement? Edit on GitHub here
and see edit history here