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
| Option | Type | Default | Description |
|---|---|---|---|
defaultValue | T | — | Value 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 |
ttl | number | — | Time-to-live in milliseconds; 0 or omitted = no expiry |
version | number | 1 | Schema version of the stored data |
migrations | Migration[] | [] | Migration functions run when stored version differs from version |
encrypt | boolean | EncryptOptions | false | Enable AES-GCM encryption |
compress | boolean | CompressOptions | false | Compress the stored envelope via the Compression Streams API. Applied before encrypt, so compression still works on the plaintext (compressed ciphertext yields no size benefit) |
sign | boolean | SignOptions | false | HMAC-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 |
sync | boolean | SyncOptions | false | Enable cross-tab sync via BroadcastChannel |
debounce | number | — | Coalesce writes: only persist debounce ms after the last change. Mutually exclusive with throttle (throttle wins if both are set) |
throttle | number | — | Write at most once every throttle ms even during continuous changes, instead of only after they stop |
history | number | — | Keep up to this many past values in memory for undo()/redo(). Not persisted — resets on reload |
evictOnQuota | boolean | { max?: number } | false | On 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 |
serializer | Serializer<T> | JSON serializer | Custom serialize / deserialize pair |
onError | (err: StorageError) => void | — | Called instead of throwing on quota exceeded, parse errors, crypto errors, invalid signatures, or other write failures |
onExpire | (key: string) => void | — | Called when a TTL-expired key is removed on read |
onMigrate | (from: number, to: number) => void | — | Called after a successful migration |
Return value
| Property | Type | Description |
|---|---|---|
value | Ref<T> | Reactive two-way binding; assigning writes to storage |
isReady | Ref<boolean> | false until the initial async read completes (important for IndexedDB and encrypted values) |
error | Ref<StorageError | null> | Last error, null if none |
expiry | ComputedRef<Date | null> | When the key expires, null if no TTL |
canUndo / canRedo | ComputedRef<boolean> | Whether undo() / redo() currently does anything (always false unless history is set) |
remove() | void | Delete 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() | void | Navigate 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 immediatelySession 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 | nullError 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.