useSessionStorage()
Persist the state with session storage so that it remains after a page refresh. This can be useful to record session information. This hook is used in the same way as useState except that you must pass the storage key in the 1st parameter. If the window object is not present (as in SSR), useSessionStorage()
will return the default value.
Related hooks:
The Hook
1import {2 Dispatch,3 SetStateAction,4 useCallback,5 useEffect,6 useState,7} from 'react'89import { useEventCallback } from '../useEventCallback'10// See: https://usehooks-ts.com/react-hook/use-event-listener11import { useEventListener } from '../useEventListener'1213declare global {14 interface WindowEventMap {15 'session-storage': CustomEvent16 }17}1819type SetValue<T> = Dispatch<SetStateAction<T>>2021function useSessionStorage<T>(key: string, initialValue: T): [T, SetValue<T>] {22 // Get from session storage then23 // parse stored json or return initialValue24 const readValue = useCallback((): T => {25 // Prevent build error "window is undefined" but keep keep working26 if (typeof window === 'undefined') {27 return initialValue28 }2930 try {31 const item = window.sessionStorage.getItem(key)32 return item ? (parseJSON(item) as T) : initialValue33 } catch (error) {34 console.warn(`Error reading sessionStorage key “${key}”:`, error)35 return initialValue36 }37 }, [initialValue, key])3839 // State to store our value40 // Pass initial state function to useState so logic is only executed once41 const [storedValue, setStoredValue] = useState<T>(readValue)4243 // Return a wrapped version of useState's setter function that ...44 // ... persists the new value to sessionStorage.45 const setValue: SetValue<T> = useEventCallback(value => {46 // Prevent build error "window is undefined" but keeps working47 if (typeof window == 'undefined') {48 console.warn(49 `Tried setting sessionStorage key “${key}” even though environment is not a client`,50 )51 }5253 try {54 // Allow value to be a function so we have the same API as useState55 const newValue = value instanceof Function ? value(storedValue) : value5657 // Save to session storage58 window.sessionStorage.setItem(key, JSON.stringify(newValue))5960 // Save state61 setStoredValue(newValue)6263 // We dispatch a custom event so every useSessionStorage hook are notified64 window.dispatchEvent(new Event('session-storage'))65 } catch (error) {66 console.warn(`Error setting sessionStorage key “${key}”:`, error)67 }68 })6970 useEffect(() => {71 setStoredValue(readValue())72 // eslint-disable-next-line react-hooks/exhaustive-deps73 }, [])7475 const handleStorageChange = useCallback(76 (event: StorageEvent | CustomEvent) => {77 if ((event as StorageEvent)?.key && (event as StorageEvent).key !== key) {78 return79 }80 setStoredValue(readValue())81 },82 [key, readValue],83 )8485 // this only works for other documents, not the current one86 useEventListener('storage', handleStorageChange)8788 // this is a custom event, triggered in writeValueTosessionStorage89 // See: useSessionStorage()90 useEventListener('session-storage', handleStorageChange)9192 return [storedValue, setValue]93}9495export default useSessionStorage9697// A wrapper for "JSON.parse()"" to support "undefined" value98function parseJSON<T>(value: string | null): T | undefined {99 try {100 return value === 'undefined' ? undefined : JSON.parse(value ?? '')101 } catch {102 console.log('parsing error on', { value })103 return undefined104 }105}
Usage
1import React from 'react'23import { useSessionStorage } from 'usehooks-ts'45export default function Component() {6 const [value, setValue] = useSessionStorage('test-key', 0)78 return (9 <div>10 <p>Count: {value}</p>11 <button onClick={() => setValue(x => x + 1)}>Increment</button>12 <button onClick={() => setValue(x => x - 1)}>Decrement</button>13 </div>14 )15}
See a way to make this page better?
Edit there »