Skip to content

Commit

Permalink
feat(useStorage): add waitOnMounted option for SSR (#3504)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
posva and antfu committed Nov 9, 2023
1 parent 37e866c commit dc6f2e8
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
23 changes: 21 additions & 2 deletions packages/core/useStorage/index.test.ts
@@ -1,7 +1,7 @@
import { debounceFilter, promiseTimeout } from '@vueuse/shared'
import { isVue3, ref, toRaw } from 'vue-demi'
import { defineComponent, isVue3, nextTick, ref, toRaw } from 'vue-demi'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { nextTwoTick, useSetup } from '../../.test'
import { mount, nextTwoTick, useSetup } from '../../.test'
import { StorageSerializers, customStorageEventName, useStorage } from '.'

const KEY = 'custom-key'
Expand Down Expand Up @@ -468,6 +468,25 @@ describe('useStorage', () => {
expect(console.error).toHaveBeenCalledWith(new Error('write item error'))
})

it('initOnMounted', async () => {
storage.setItem(KEY, 'random')

const vm = mount(defineComponent({
setup() {
const basicRef = useStorage(KEY, '', storage, { initOnMounted: true })
expect(basicRef.value).toBe('')

return {
basicRef,
}
},
}))

await nextTick()

expect(vm.basicRef).toBe('random')
})

it.each([
1,
'a',
Expand Down
23 changes: 19 additions & 4 deletions packages/core/useStorage/index.ts
@@ -1,6 +1,6 @@
import { nextTick, ref, shallowRef } from 'vue-demi'
import type { Awaitable, ConfigurableEventFilter, ConfigurableFlush, MaybeRefOrGetter, RemovableRef } from '@vueuse/shared'
import { pausableWatch, toValue } from '@vueuse/shared'
import { pausableWatch, toValue, tryOnMounted } from '@vueuse/shared'
import type { StorageLike } from '../ssr-handlers'
import { getSSRHandler } from '../ssr-handlers'
import { useEventListener } from '../useEventListener'
Expand Down Expand Up @@ -112,6 +112,13 @@ export interface UseStorageOptions<T> extends ConfigurableEventFilter, Configura
* @default false
*/
shallow?: boolean

/**
* Wait for the component to be mounted before reading the storage.
*
* @default false
*/
initOnMounted?: boolean
}

export function useStorage(key: string, defaults: MaybeRefOrGetter<string>, storage?: StorageLike, options?: UseStorageOptions<string>): RemovableRef<string>
Expand Down Expand Up @@ -143,6 +150,7 @@ export function useStorage<T extends(string | number | boolean | object | null)>
onError = (e) => {
console.error(e)
},
initOnMounted,
} = options

const data = (shallow ? shallowRef : ref)(typeof defaults === 'function' ? defaults() : defaults) as RemovableRef<T>
Expand Down Expand Up @@ -170,11 +178,18 @@ export function useStorage<T extends(string | number | boolean | object | null)>
)

if (window && listenToStorageChanges) {
useEventListener(window, 'storage', update)
useEventListener(window, customStorageEventName, updateFromCustomEvent)
tryOnMounted(() => {
// this should be fine since we are in a mounted hook
useEventListener(window, 'storage', update)
useEventListener(window, customStorageEventName, updateFromCustomEvent)
if (initOnMounted)
update()
})
}

update()
// avoid reading immediately to avoid hydration mismatch when doing SSR
if (!initOnMounted)
update()

return data

Expand Down

0 comments on commit dc6f2e8

Please sign in to comment.