useSessionStorage is a hook that binds React state to sessionStorage under a given key.
- Initializes the value from storage (if there is a valid string), otherwise from
initialValue. - Returns a tuple
[value, setValue]. setValueaccepts either a direct value or a functional updater(prev) => next.- Supports customizable
serializer/deserializer. - Data lives within the current tab/window and is cleared when the browser session ends (unlike
localStorage).
function useSessionStorage<ValueType = undefined>(
key: string,
initialValue?: undefined,
options?: UseSessionStorageOptions<ValueType>,
): UseSessionStorageReturn<ValueType | undefined>;
function useSessionStorage<ValueType>(
key: string,
initialValue: ValueType | (() => ValueType),
options?: UseSessionStorageOptions<ValueType>,
): UseSessionStorageReturn<ValueType>;-
Parameters
key— the key insessionStorage.initialValue?— initial value or factory. Used if storage does not contain a valid string.options?— serialization settings:serializer?: (key, value) => string— converts a value to a string before writing.deserializer?: (key, raw) => Value | undefined— parses a string from storage. Returnundefinedto treat as “no value”.
-
Returns:
UseSessionStorageReturn<Value>— tuple[value, setValue].
const [step, setStep] = useSessionStorage<number>('wizard:step', 1);
const next = () => setStep((prev) => (prev ?? 1) + 1);const [draft, setDraft] = useSessionStorage<string | undefined>('form:draft');
// remove the stored value and set state to undefined
setDraft(undefined);type Filter = { q: string; page: number };
const serializer = (_key: string, value: Filter) => JSON.stringify({ root: value });
const deserializer = (_key: string, rawValue: string): Filter | undefined => {
const parsed = JSON.parse(rawValue);
return parsed?.root;
};
const [filter, setFilter] = useSessionStorage<Filter>(
'list:filter',
{ q: '', page: 1 },
{ serializer, deserializer },
);-
Initialization
- On mount, reads the
rawstring fromsessionStorage[key]and appliesdeserializer. - If
deserializerreturnsundefined,initialValueis used.
- On mount, reads the
-
Update
setValue(next)writes a new string (viaserializer) or removes the key ifnext === undefined.- A functional updater
(prev) => nextis supported.
-
Key change
- When
keychanges, the hook re‑reads the value for the new key, applyingdeserializeragain.
- When
-
Scope & lifetime
- Values in
sessionStorageare not shared across tabs and are cleared when the tab/window closes or the browser session ends.
- Values in
- Wizards, temporary filters, and per‑tab page state.
- Drafts and input that should survive reloads but not session termination.
- Ephemeral UI settings for the current window.
- You need persistence between sessions — use
useLocalStorage. - Large or complex structures — consider
IndexedDB. - Sensitive data without encryption.
-
Expecting cross‑tab sharing
sessionStorageis tab‑scoped; it doesn’t sync automatically.
-
Expecting
initialValueaftersetValue(undefined)- In the current mount,
valuebecomesundefined.initialValueis applied only on the next mount (if the key is absent).
- In the current mount,
-
Inconsistent storage format
- Changing
serializer/deserializermay break old values — plan migrations.
- Changing
Exported types
UseSessionStorageReturn<Value>—[value: Value, setValue: (action) => void].UseSessionStorageOptions<Value>— options forserializer/deserializer.UseSessionStorageSetAction<Value>—Value | ((prev: Value) => Value).