Skip to main content
Persists state in sessionStorage under a given key and keeps React state in sync. Values are scoped to the current browser tab/session and follow the shared storage hook contract.

Usage

import { useSessionStorage } from '@kuzenbo/hooks';

function Demo() {
  const [value, setValue, removeValue] = useSessionStorage({
    key: 'session-key',
    defaultValue: 'default value',
  });

  return (
    <div>
      <p>Value: {value}</p>
      <button onClick={() => setValue('new value')}>Set Value</button>
      <button onClick={removeValue}>Remove Value</button>
    </div>
  );
}

Function Signature

function useSessionStorage<T = string>(
  props: UseStorageOptions<T>
): UseStorageReturnValue<T>

type UseStorageReturnValue<T> = [
  T,
  (val: T | ((prevState: T) => T)) => void,
  () => void,
]

Parameters

props
UseStorageOptions<T>
required
Storage options such as key, default value, sync behavior, and serializers.
props.key
string
required
Storage key under which the value will be saved.
props.defaultValue
T
Default value that will be set if no value is found in storage.
props.getInitialValueInEffect
boolean
If true, value will be updated in useEffect after mount. Defaults to true.
props.sync
boolean
Determines whether the value must be synced between browser tabs. Defaults to true.
props.serialize
(value: T) => string
Function to serialize value into string to be saved in storage.
props.deserialize
(value: string | undefined) => T
Function to deserialize string value from storage to value.

Return Value

Returns a tuple with three elements:
[0]
T
Current value from sessionStorage.
[1]
(val: T | ((prevState: T) => T)) => void
Callback to set value in storage. Supports updater function pattern.
[2]
() => void
Callback to remove value from storage.

Examples

Basic Usage

import { useSessionStorage } from '@kuzenbo/hooks';

function FormExample() {
  const [formData, setFormData] = useSessionStorage({
    key: 'form-draft',
    defaultValue: '',
  });

  return (
    <div>
      <textarea
        value={formData}
        onChange={(e) => setFormData(e.target.value)}
        placeholder="Your draft is saved in this tab session"
      />
    </div>
  );
}

With Complex Objects

import { useSessionStorage } from '@kuzenbo/hooks';

interface FormState {
  step: number;
  data: Record<string, string>;
}

function MultiStepForm() {
  const [formState, setFormState] = useSessionStorage<FormState>({
    key: 'multi-step-form',
    defaultValue: { step: 1, data: {} },
  });

  return (
    <div>
      <p>Current Step: {formState.step}</p>
      <button onClick={() => setFormState({ ...formState, step: formState.step + 1 })}>
        Next Step
      </button>
    </div>
  );
}

Tab-Specific Counter

import { useSessionStorage } from '@kuzenbo/hooks';

function TabCounter() {
  const [count, setCount, removeCount] = useSessionStorage({
    key: 'tab-counter',
    defaultValue: 0,
  });

  return (
    <div>
      <p>This tab's count: {count}</p>
      <button onClick={() => setCount((prev) => prev + 1)}>Increment</button>
      <button onClick={removeCount}>Reset</button>
    </div>
  );
}

Wizard State Persistence

import { useSessionStorage } from '@kuzenbo/hooks';

interface WizardState {
  currentStep: number;
  completedSteps: number[];
  userData: Record<string, unknown>;
}

function Wizard() {
  const [wizardState, setWizardState] = useSessionStorage<WizardState>({
    key: 'wizard-progress',
    defaultValue: {
      currentStep: 0,
      completedSteps: [],
      userData: {},
    },
  });

  const completeStep = (step: number) => {
    setWizardState((prev) => ({
      ...prev,
      completedSteps: [...prev.completedSteps, step],
      currentStep: step + 1,
    }));
  };

  return <div>{/* Wizard UI */}</div>;
}

Utility Function

readSessionStorageValue

Read a value from sessionStorage without using the hook:
import { readSessionStorageValue } from '@kuzenbo/hooks';

const value = readSessionStorageValue({
  key: 'my-session-key',
  defaultValue: 'default',
});

Differences from useLocalStorage

  • Values persist only for the current tab/window session
  • Data is cleared when the tab/window is closed
  • Perfect for temporary state like form drafts or wizard progress
  • Does not persist across browser restarts

Build docs developers (and LLMs) love