use Local Storage (React)
Save to localStorage
whenever state changes and read from it for the first
render. More primitive (and minimal) ancestor of
useSyncedLocalStorage
.
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]
}
import { useCallback, useEffect, useState } from 'react'
const useLocalStorage = (key, initialValue) => {
const [state, setState] = useState(() => {
const cached = localStorage.getItem(key)
if (!cached) return initialValue
try {
return JSON.parse(cached)
} 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 theclearState
function to prevent unnecessary re-renders if you use theclearState
function inside auseEffect
oruseCallback
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 outuseSyncedLocalStorage
Usage
typescriptjavascript
const Example = () => {
const [input, setInput] = useLocalStorage('example:input', '')
return (
<>
<input value={input} onChange={e => setInput(e.target.value)} />
</>
)
}
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.