useSessionStorage
useSessionStorage persists React state in sessionStorage with safe JSON serialization, functional updates, and explicit reset and remove helpers. Values last for the browser tab session and clear when the tab closes.
Live Example
Session draft editor
This demo shows the common pattern: state stays in sync with sessionStorage for the lifetime of the tab.
Session draft
sessionStorage-backed state
While this tab stays open, navigation and refreshes keep this text. The hook updates React state and `sessionStorage` together, with reset and remove helpers for the stored key.
Import
import { useSessionStorage } from "react-rsc-kit/client";Signature
const { value, setValue, remove, reset, isSupported } = useSessionStorage<T>(key, initialValue);Parameters
| Name | Type | Description |
|---|---|---|
key | string | sessionStorage key used to read, write, remove, and reset the stored value. |
initialValue | T | () => T | Fallback value used when storage is empty, invalid, or unavailable. Supports lazy initialization. |
Returns
| Key | Type | Description |
|---|---|---|
value | T | Current React state value. |
setValue | Dispatch<SetStateAction<T>> | Updates state and writes the next value to sessionStorage. Supports functional updates. |
remove | () => void | Removes the storage key and resets state back to the fallback value. |
reset | () => void | Restores the fallback value and writes it back to sessionStorage. |
isSupported | boolean | Whether sessionStorage is available in the current environment. |
Usage
"use client";
import { useSessionStorage } from "react-rsc-kit/client";
export function DraftMessage() {
const { value: draft, setValue, remove } = useSessionStorage("draft-message", "");
return (
<div>
<textarea value={draft} onChange={(event) => setValue(event.target.value)} />
<button type="button" onClick={remove}>
Clear draft
</button>
</div>
);
}"use client";
import { useSessionStorage } from "react-rsc-kit/client";
interface UserPreferences {
compactMode: boolean;
itemsPerPage: number;
tags: string[];
}
export function PreferencesPanel() {
const {
value: preferences,
setValue,
reset,
} = useSessionStorage<UserPreferences>("user-preferences", {
compactMode: false,
itemsPerPage: 20,
tags: ["react", "typescript"],
});
return (
<div>
<p>{preferences.itemsPerPage} items</p>
<button
type="button"
onClick={() =>
setValue((currentValue) => ({
...currentValue,
compactMode: !currentValue.compactMode,
}))
}
>
Toggle compact mode
</button>
<button type="button" onClick={reset}>
Reset preferences
</button>
</div>
);
}Notes
- The hook reads existing stored JSON first and falls back to
initialValuewhen the key is missing, malformed, or unavailable. remove()andreset()always resolve the fallback from the latestinitialValueyou pass for the samekey(handy when defaults come from props). ChanginginitialValuedoes not overwrite an existing stored value until you callsetValue,reset, orremove.setValueavoids writing to storage when the resolved value is unchanged (Object.is), which reduces work for no-op functional updates.remove()clears the key fromsessionStorage, whilereset()writes the fallback value back into storage.- Explicit
undefinedvalues are preserved by the hook’s serializer, but values still need to be JSON-serializable to persist correctly. - In non-browser environments, the hook falls back to React state and reports
isSupportedasfalse. - Unlike
localStorage,sessionStorageis scoped to the current tab and does not persist after the tab is closed.
Last updated on