Skip to content

useLocalStorage / useSessionStorage ​

Reactive sync with localStorage and sessionStorage. Persist user preferences like theme, table page size, or form drafts across sessions (localStorage) or within the current tab (sessionStorage).

useLocalStorage ​

Persists across browser sessions. Use for theme, page size, sidebar state, etc.

vue
<template>
  <BvSelect v-model="pageSize" :options="pageSizeOptions" />
</template>

<script setup>
import { BvSelect } from "@baklavue/ui";
import { useLocalStorage } from "@baklavue/composables";

const pageSize = useLocalStorage("table-page-size", 10);
const pageSizeOptions = [
  { value: 10, text: "10" },
  { value: 25, text: "25" },
  { value: 50, text: "50" },
];
</script>

useSessionStorage ​

Persists only for the current tab/session. Use for form drafts, temporary filters, etc.

vue
<script setup>
import { useSessionStorage } from "@baklavue/composables";

const draft = useSessionStorage("form-draft", null);
</script>

With useBaklavaTheme ​

vue
<script setup>
import { useBaklavaTheme, useLocalStorage } from "@baklavue/composables";

const themePreset = useLocalStorage("theme-preset", "vue");
const { applyTheme } = useBaklavaTheme();

watch(themePreset, (preset) => applyTheme({ preset }), { immediate: true });
</script>

With usePagination ​

vue
<script setup>
import { usePagination, useLocalStorage } from "@baklavue/composables";

const savedPageSize = useLocalStorage("pagination-page-size", 10);
const { currentPage, pageSize, totalItems, slice } = usePagination({
  pageSize: savedPageSize.value,
});

watch(pageSize, (size) => (savedPageSize.value = size));
</script>

Options ​

useLocalStorage and useSessionStorage accept an optional third parameter.

typescript
interface UseStorageOptions<T> {
  /** Merge default with stored value when both are objects. Default: false */
  mergeDefaults?: boolean | ((storageValue: T, defaults: T) => T);
  /** Listen to storage events for cross-tab sync. Default: true for localStorage, false for sessionStorage */
  listenToStorageChanges?: boolean;
  /** Custom serializer. Default: JSON */
  serializer?: { read: (raw: string) => T; write: (value: T) => string };
  /** Error callback. Default: silent */
  onError?: (error: unknown) => void;
}

mergeDefaults ​

When you add new properties to your default object, existing stored values won't have them. Enable mergeDefaults: true for a shallow merge:

vue
<script setup>
import { useLocalStorage } from "@baklavue/composables";

// If storage has { theme: "vue" } but default adds compact, merged result includes both
const prefs = useLocalStorage("prefs", { theme: "vue", compact: false }, {
  mergeDefaults: true,
});
</script>

Or pass a custom merge function for deep merge:

typescript
import { useLocalStorage } from "@baklavue/composables";

const prefs = useLocalStorage("prefs", defaultPrefs, {
  mergeDefaults: (stored, defaults) => ({ ...defaults, ...stored }),
});

listenToStorageChanges ​

Changes in other tabs update the ref automatically. Enabled by default for useLocalStorage; disabled for useSessionStorage (sessionStorage is tab-scoped).

Custom serializer ​

Store Map, Set, Date, or custom formats:

typescript
import { useLocalStorage } from "@baklavue/composables";

const count = useLocalStorage("count", 0, {
  serializer: {
    read: (v) => parseFloat(v) || 0,
    write: (v) => String(v),
  },
});

const lastVisit = useLocalStorage("last-visit", new Date(), {
  serializer: {
    read: (v) => new Date(v),
    write: (v) => v.toISOString(),
  },
});

onError ​

Handle quota exceeded or parse errors:

typescript
const prefs = useLocalStorage("prefs", {}, {
  onError: (e) => console.error("Storage error:", e),
});

API ​

useLocalStorage ​

typescript
useLocalStorage<T>(key: string, defaultValue: T): Ref<T>
useLocalStorage<T>(key: string, defaultValue: T, options: UseStorageOptions<T>): Ref<T>
ParameterTypeDescription
keystringStorage key
defaultValueTDefault when key is missing or on SSR
optionsUseStorageOptions<T>Optional: mergeDefaults, listenToStorageChanges, serializer, onError

useSessionStorage ​

typescript
useSessionStorage<T>(key: string, defaultValue: T): Ref<T>
useSessionStorage<T>(key: string, defaultValue: T, options: UseStorageOptions<T>): Ref<T>
ParameterTypeDescription
keystringStorage key
defaultValueTDefault when key is missing or on SSR
optionsUseStorageOptions<T>Optional: mergeDefaults, listenToStorageChanges, serializer, onError

Notes ​

  • Values are JSON-serialized by default. Primitives, objects, and arrays are supported.
  • On SSR, returns defaultValue (storage is not available).
  • Changes to the ref are written to storage (with { deep: true } for objects).
  • Cross-tab sync is enabled for useLocalStorage by default.

TypeScript Support ​

typescript
import { useLocalStorage, useSessionStorage, type UseStorageOptions } from "@baklavue/composables";

const pageSize = useLocalStorage<number>("page-size", 10);
const prefs = useLocalStorage("prefs", { theme: "vue", compact: false });
const draft = useSessionStorage<string | null>("draft", null);

// With options
const prefsWithMerge = useLocalStorage("prefs", { theme: "vue", compact: false }, {
  mergeDefaults: true,
});