useSessionStorage
The same hook as useLocalStorage, backed by sessionStorage. The value survives a reload and dies with the tab, which is what state belonging to one visit
should do.
Basic Usage
Type something below and reload the page: the draft comes back. Open this page in a new tab and it is empty there, because each tab has a store of its own.
0 characters<script lang="ts">
import { useSessionStorage } from 'sv5ui';
// Lives for the life of this tab. A reload keeps it, a new tab starts
// clean, and closing the tab throws it away.
const draft = useSessionStorage('comment-draft', '');
</script>
<textarea bind:value={draft.current}></textarea>
<button onclick={draft.remove}>Discard draft</button>A Multi-step Form
A half-finished checkout is the clearest case for this store. It should survive a mistaken reload, and it should not still be sitting there tomorrow, nor leak into another tab where the same person is buying something else. Fill in a step, reload, and carry on where you were.
<script lang="ts">
import { useSessionStorage } from 'sv5ui';
interface Checkout {
step: number;
email: string;
shipping: string;
}
// A half-finished checkout is exactly the kind of state that should
// survive an accidental reload and should not follow the customer into
// tomorrow, or into another tab where they are buying something else.
const checkout = useSessionStorage<Checkout>('checkout', {
step: 1,
email: '',
shipping: 'standard'
});
function next() {
checkout.current = { ...checkout.current, step: checkout.current.step + 1 };
}
async function submit() {
await placeOrder(checkout.current);
// Clear the slot rather than writing the defaults back into it.
checkout.remove();
}
</script>Clearing with remove() after a successful order empties the slot rather than writing the defaults into it, so the next
visit starts from whatever the defaults are then.
Keys Work the Same Way
Everything useLocalStorage does with keys applies here: a getter is tracked, so a draft can follow whichever thread is open, and a null key makes the hook inert so nothing is stored when there is nothing to store.
See Keys That Change for a live demo of the same behavior.
<script lang="ts">
import { useSessionStorage } from 'sv5ui';
let { threadId }: { threadId: string | null } = $props();
// Everything useLocalStorage does with keys works here too: a getter is
// tracked, and a null key makes the hook inert, which is how a draft can
// follow whichever thread is open and stop persisting when none is.
const draft = useSessionStorage(() => (threadId ? `draft:${threadId}` : null), '');
</script>
{#if !draft.enabled}
<p>Open a thread to start writing</p>
{/if}Equivalent Calls
This hook is useLocalStorage with storage: 'session' already applied, and with that option removed from its type so it cannot be contradicted.
Use the named hook when the store is part of what the value means, and the option when it is chosen at runtime.
import { useLocalStorage, useSessionStorage } from 'sv5ui';
// These two calls are the same thing.
const a = useSessionStorage('draft', '');
const b = useLocalStorage('draft', '', { storage: 'session' });
// The options type of useSessionStorage has storage removed, so the store
// cannot be contradicted after the fact:
// Omit<UseLocalStorageOptions<T>, 'storage'>
const c = useSessionStorage('draft', '', { syncTabs: false });Local or Session
Same API, different lifetime.
| Question | useLocalStorage |
|---|---|
Survives a reload | Yes |
Survives closing the tab | Yes |
Shared with another tab | Yes, one store per origin |
Cross-tab storage events | Received, and filtered to the local area |
Typical use | Theme, layout, preferences, anything that should feel remembered |
Parameters
| Parameter | Type | Default |
|---|---|---|
key | StorageKey | (() => StorageKey) | - |
initial | T | - |
options | Omit<UseLocalStorageOptions<T>, 'storage'> | {} |
Return
| Property | Type |
|---|---|
current | T |
enabled | readonly boolean |
remove | () => void |