Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply VueUse composables in Vue 3/Nuxt projects to replace custom implementations with battle-tested utilities.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/useStorage.md
1---2category: State3related: useLocalStorage, useSessionStorage, useStorageAsync4---56# useStorage78Create a reactive ref that can be used to access & modify [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) or [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage).910Uses localStorage by default, other storage sources be specified via third argument.1112## Usage1314::: tip15When using with Nuxt 3, this function will **NOT** be auto imported in favor of Nitro's built-in [`useStorage()`](https://nitro.unjs.io/guide/storage). Use explicit import if you want to use the function from VueUse.16:::1718```ts19import { useStorage } from '@vueuse/core'2021// bind object22const state = useStorage('my-store', { hello: 'hi', greeting: 'Hello' })2324// bind boolean25const flag = useStorage('my-flag', true) // returns Ref<boolean>2627// bind number28const count = useStorage('my-count', 0) // returns Ref<number>2930// bind string with SessionStorage31const id = useStorage('my-id', 'some-string-id', sessionStorage) // returns Ref<string>3233// delete data from storage34state.value = null35```3637## Merge Defaults3839By default, `useStorage` will use the value from storage if it is present and ignores the default value. Be aware that when you are adding more properties to the default value, the key might be `undefined` if client's storage does not have that key.4041```ts42import { useStorage } from '@vueuse/core'43// ---cut---44localStorage.setItem('my-store', '{"hello": "hello"}')4546const state = useStorage('my-store', { hello: 'hi', greeting: 'hello' }, localStorage)4748console.log(state.value.greeting) // undefined, since the value is not presented in storage49```5051To solve that, you can enable `mergeDefaults` option.5253```ts54import { useStorage } from '@vueuse/core'55// ---cut---56localStorage.setItem('my-store', '{"hello": "nihao"}')5758const state = useStorage(59'my-store',60{ hello: 'hi', greeting: 'hello' },61localStorage,62{ mergeDefaults: true } // <--63)6465console.log(state.value.hello) // 'nihao', from storage66console.log(state.value.greeting) // 'hello', from merged default value67```6869When setting it to true, it will perform a **shallow merge** for objects. You can pass a function to perform custom merge (e.g. deep merge), for example:7071```ts72import { useStorage } from '@vueuse/core'73// ---cut---74const state = useStorage(75'my-store',76{ hello: 'hi', greeting: 'hello' },77localStorage,78{ mergeDefaults: (storageValue, defaults) => deepMerge(defaults, storageValue) } // <--79)80```8182## Custom Serialization8384By default, `useStorage` will smartly use the corresponding serializer based on the data type of provided default value. For example, `JSON.stringify` / `JSON.parse` will be used for objects, `Number.toString` / `parseFloat` for numbers, etc.8586You can also provide your own serialization function to `useStorage`:8788```ts89import { useStorage } from '@vueuse/core'9091useStorage(92'key',93{},94undefined,95{96serializer: {97read: (v: any) => v ? JSON.parse(v) : null,98write: (v: any) => JSON.stringify(v),99},100},101)102```103104Please note when you provide `null` as the default value, `useStorage` can't assume the data type from it. In this case, you can provide a custom serializer or reuse the built-in ones explicitly.105106```ts107import { StorageSerializers, useStorage } from '@vueuse/core'108109const objectLike = useStorage('key', null, undefined, { serializer: StorageSerializers.object })110objectLike.value = { foo: 'bar' }111```112113### Built-in Serializers114115The following serializers are available via `StorageSerializers`:116117| Type | Description |118| --------- | ------------------------------------- |119| `string` | Plain string |120| `number` | Number (via `parseFloat`) |121| `boolean` | Boolean |122| `object` | JSON object/array |123| `map` | JavaScript `Map` |124| `set` | JavaScript `Set` |125| `date` | JavaScript `Date` (via `toISOString`) |126| `any` | Raw string passthrough |127128```ts129import { StorageSerializers, useStorage } from '@vueuse/core'130131const myMap = useStorage('my-map', new Map(), undefined, {132serializer: StorageSerializers.map,133})134```135136## Options137138```ts139useStorage('key', defaults, storage, {140// Watch for deep changes in objects/arrays (default: true)141deep: true,142// Sync across tabs via storage events (default: true)143listenToStorageChanges: true,144// Write default value to storage if not present (default: true)145writeDefaults: true,146// Use shallowRef instead of ref (default: false)147shallow: false,148// Initialize only after component is mounted (default: false)149initOnMounted: false,150// Custom error handler (default: console.error)151onError: e => console.error(e),152// Watch flush timing (default: 'pre')153flush: 'pre',154})155```156157## Reactive Key158159The storage key can be a ref or getter, and the data will be updated when the key changes:160161```ts162import { useStorage } from '@vueuse/core'163164const userId = ref('user-1')165const userData = useStorage(166() => `user-data-${userId.value}`,167{ name: '' },168)169170// Changing the key will read from the new storage location171userId.value = 'user-2'172```173174## Type Declarations175176```ts177export interface Serializer<T> {178read: (raw: string) => T179write: (value: T) => string180}181export interface SerializerAsync<T> {182read: (raw: string) => Awaitable<T>183write: (value: T) => Awaitable<string>184}185export declare const StorageSerializers: Record<186"boolean" | "object" | "number" | "any" | "string" | "map" | "set" | "date",187Serializer<any>188>189export declare const customStorageEventName = "vueuse-storage"190export interface StorageEventLike {191storageArea: StorageLike | null192key: StorageEvent["key"]193oldValue: StorageEvent["oldValue"]194newValue: StorageEvent["newValue"]195}196export interface UseStorageOptions<T>197extends ConfigurableEventFilter, ConfigurableWindow, ConfigurableFlush {198/**199* Watch for deep changes200*201* @default true202*/203deep?: boolean204/**205* Listen to storage changes, useful for multiple tabs application206*207* @default true208*/209listenToStorageChanges?: boolean210/**211* Write the default value to the storage when it does not exist212*213* @default true214*/215writeDefaults?: boolean216/**217* Merge the default value with the value read from the storage.218*219* When setting it to true, it will perform a **shallow merge** for objects.220* You can pass a function to perform custom merge (e.g. deep merge), for example:221*222* @default false223*/224mergeDefaults?: boolean | ((storageValue: T, defaults: T) => T)225/**226* Custom data serialization227*/228serializer?: Serializer<T>229/**230* On error callback231*232* Default log error to `console.error`233*/234onError?: (error: unknown) => void235/**236* Use shallow ref as reference237*238* @default false239*/240shallow?: boolean241/**242* Wait for the component to be mounted before reading the storage.243*244* @default false245*/246initOnMounted?: boolean247}248export declare function useStorage(249key: MaybeRefOrGetter<string>,250defaults: MaybeRefOrGetter<string>,251storage?: StorageLike,252options?: UseStorageOptions<string>,253): RemovableRef<string>254export declare function useStorage(255key: MaybeRefOrGetter<string>,256defaults: MaybeRefOrGetter<boolean>,257storage?: StorageLike,258options?: UseStorageOptions<boolean>,259): RemovableRef<boolean>260export declare function useStorage(261key: MaybeRefOrGetter<string>,262defaults: MaybeRefOrGetter<number>,263storage?: StorageLike,264options?: UseStorageOptions<number>,265): RemovableRef<number>266export declare function useStorage<T>(267key: MaybeRefOrGetter<string>,268defaults: MaybeRefOrGetter<T>,269storage?: StorageLike,270options?: UseStorageOptions<T>,271): RemovableRef<T>272export declare function useStorage<T = unknown>(273key: MaybeRefOrGetter<string>,274defaults: MaybeRefOrGetter<null>,275storage?: StorageLike,276options?: UseStorageOptions<T>,277): RemovableRef<T>278```279