Sync localStorage Between Tabs
Using localStorage
is great for storing simple user preferences such as
the expanded/collapsed state of a sidebar, or the light/dark theme
preference for the site. An often overlooked but useful feature of
localStorage
is the ability to sync changes between open tabs.
In the code snippet below, we create a simple useLocalStorage
hook which
is a wrapper around useState
to load the initial value from
localStorage
and store changes to the value back into localStorage
.
The magic comes in when we utilize window.addEventListener("storage")
to
listen for changes to localStorage
from other tabs on the same domain.
When another tab changes localStorage
, we’ll receive an event which we
can use to update the state in the current tab. Now if we have two open
tabs and toggle the website theme to dark mode, both tabs will become dark.
No need to refresh!
This feels quite magical as a user and it’s incredibly simple to implement!
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const json = localStorage.getItem(key)
return json ? JSON.parse(json) : initialValue
})
useEffect(() => {
function handleStorageChange(event: StorageEvent) {
if (event.key === key) {
setValue(e.newValue ? JSON.parse(e.newValue) : initialValue)
}
}
window.addEventListener("storage", handleStorageChange)
return () => window.removeEventListener("storage", handleStorageChange)
}, [initialValue, key])
const setValueAndStore = useCallback(
(value: T) => {
window.localStorage.setItem(key, JSON.stringify(value))
setValue(value)
},
[key],
)
return [value, setValueAndStore] as const
}