Skip to content

API Reference

useStorage

The core composable. Works with localStorage, sessionStorage, and an in-memory fallback.

ts
useStorage<T>(key: string, options: StorageOptions<T>): UseStorageReturn<T>

Options

OptionTypeDefaultDescription
defaultValueTValue returned when the key is absent or has expired
target'local' | 'session' | 'memory' | 'indexeddb''local'Storage backend. 'indexeddb' stores through a single dedicated object store (db vue-storage-kit, store kv) — for custom databases/stores or secondary indexes, use useIndexedDB() / useIDBRef() instead
ttlnumberTime-to-live in milliseconds; 0 or omitted = no expiry
versionnumber1Schema version of the stored data
migrationsMigration[][]Migration functions run when stored version differs from version
encryptboolean | EncryptOptionsfalseEnable AES-GCM encryption
compressboolean | CompressOptionsfalseCompress the stored envelope via the Compression Streams API. Applied before encrypt, so compression still works on the plaintext (compressed ciphertext yields no size benefit)
signboolean | SignOptionsfalseHMAC-SHA256 check, applied as the outermost layer (wraps compressed/encrypted data too). Detects accidental corruption without requiring secrecy — not a defense against a user editing their own storage (see Corruption detection) — combine with encrypt for both
syncboolean | SyncOptionsfalseEnable cross-tab sync via BroadcastChannel
debouncenumberCoalesce writes: only persist debounce ms after the last change. Mutually exclusive with throttle (throttle wins if both are set)
throttlenumberWrite at most once every throttle ms even during continuous changes, instead of only after they stop
historynumberKeep up to this many past values in memory for undo()/redo(). Not persisted — resets on reload
evictOnQuotaboolean | { max?: number }falseOn QuotaExceededError, if sweeping this adapter's expired-TTL entries isn't enough, evict its least-recently-written other keys (oldest first, up to max, default 1) and retry. Off by default — deleting unrelated keys is a real side effect
serializerSerializer<T>JSON serializerCustom serialize / deserialize pair
onError(err: StorageError) => voidCalled instead of throwing on quota exceeded, parse errors, crypto errors, invalid signatures, or other write failures
onExpire(key: string) => voidCalled when a TTL-expired key is removed on read
onMigrate(from: number, to: number) => voidCalled after a successful migration

Return value

PropertyTypeDescription
valueRef<T>Reactive two-way binding; assigning writes to storage
isReadyRef<boolean>false until the initial async read completes (important for IndexedDB and encrypted values)
errorRef<StorageError | null>Last error, null if none
expiryComputedRef<Date | null>When the key expires, null if no TTL
canUndo / canRedoComputedRef<boolean>Whether undo() / redo() currently does anything (always false unless history is set)
remove()voidDelete the key from storage and reset value to defaultValue
refresh()Promise<void>Re-read from storage (useful if another process may have written)
undo() / redo()voidNavigate through values recorded via history; a no-op if history isn't set or the respective stack is empty

Examples

Basic read/write:

ts
const { value: counter } = useStorage('counter', { defaultValue: 0 })

counter.value++ // writes to localStorage immediately

Session storage:

ts
const { value: token } = useStorage('auth-token', {
  defaultValue: '',
  target: 'session',
})

TTL — auto-expire after 30 minutes:

ts
const { value: cache, expiry } = useStorage('search-cache', {
  defaultValue: [] as string[],
  ttl: 30 * 60 * 1000,
  onExpire: (key) => console.log(`${key} expired`),
})

console.log(expiry.value) // Date | null

Error handling:

ts
const { value, error } = useStorage('data', {
  defaultValue: {},
  onError: (err) => {
    if (err.type === 'quota-exceeded') showToast('Storage is full')
    if (err.type === 'parse-error') console.warn('Corrupted value, reset to default')
  },
})

Custom serializer:

ts
import type { Serializer } from 'vue-storage-kit'

const base64Serializer: Serializer<string> = {
  serialize: (v) => btoa(v),
  deserialize: (raw) => atob(raw),
}

const { value } = useStorage('encoded', {
  defaultValue: '',
  serializer: base64Serializer,
})

useLocalStorage / useSessionStorage

Shorthand composables — identical to useStorage but with target pre-set and defaultValue as the second argument (vueuse-compatible signature).

ts
useLocalStorage<T>(key: string, defaultValue: T, opts?): UseStorageReturn<T>
useSessionStorage<T>(key: string, defaultValue: T, opts?): UseStorageReturn<T>
ts
import { useLocalStorage, useSessionStorage } from 'vue-storage-kit'

const { value: settings } = useLocalStorage('settings', { theme: 'light', lang: 'en' })
const { value: draft } = useSessionStorage('draft', '')

These are drop-in replacements for @vueuse/core useLocalStorage / useSessionStorage.