feat(nuxt3): watch option for useAsyncData to auto refresh (#3722)

This commit is contained in:
pooya parsa 2022-03-16 23:49:30 +01:00 committed by GitHub
parent e3f0b31925
commit 7c0b9140c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 4 deletions

View File

@ -18,6 +18,7 @@ const {
pending: Ref<boolean>,
refresh: (force?: boolean) => Promise<void>,
error?: any
watch: WatchSource[]
} = useAsyncData(
key: string,
handler: (ctx?: NuxtApp) => Promise<Object>,
@ -35,6 +36,7 @@ const {
* _server_: whether to fetch the data on server-side (defaults to `true`)
* _transform_: a function that can be used to alter `handler` function result after resolving
* _pick_: only pick specified keys in this array from `handler` function result
* _watch_: watch reactive sources to auto refrash
Under the hood, `lazy: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience.

View File

@ -1,5 +1,6 @@
<script setup>
const { data, refresh, pending } = await useAsyncData('/api/hello', () => $fetch('/api/hello'))
const ctr = ref(0)
const { data, refresh, pending } = await useAsyncData('/api/hello', () => $fetch(`/api/hello/${ctr.value}`), { watch: [ctr] })
</script>
<template>
@ -9,6 +10,9 @@ const { data, refresh, pending } = await useAsyncData('/api/hello', () => $fetch
<NButton :disabled="pending" @click="refresh">
Refresh Data
</NButton>
<NButton :disabled="pending" @click="ctr++">
+
</NButton>
</div>
<template #tips>
<div>

View File

@ -1 +1 @@
export default () => `Hello world! (Generated at ${new Date().toGMTString()})`
export default req => `Hello world (${req.url.substr(1)}) (Generated at ${new Date().toGMTString()})`

View File

@ -1,5 +1,5 @@
import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance } from 'vue'
import type { Ref } from 'vue'
import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance, watch } from 'vue'
import type { Ref, WatchSource } from 'vue'
import { NuxtApp, useNuxtApp } from '#app'
export type _Transform<Input = any, Output = any> = (input: Input) => Output
@ -8,6 +8,8 @@ export type PickFrom<T, K extends Array<string>> = T extends Array<any> ? T : T
export type KeysOf<T> = Array<keyof T extends string ? keyof T : string>
export type KeyOfRes<Transform extends _Transform> = KeysOf<ReturnType<Transform>>
type MultiWatchSources = (WatchSource<unknown> | object)[];
export interface AsyncDataOptions<
DataT,
Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>,
@ -18,6 +20,7 @@ export interface AsyncDataOptions<
default?: () => DataT
transform?: Transform
pick?: PickKeys
watch?: MultiWatchSources
}
export interface _AsyncData<DataT> {
@ -133,6 +136,14 @@ export function useAsyncData<
// 4. Navigation (lazy: false) - or plugin usage: await fetch
asyncData.refresh()
}
if (options.watch) {
const unwatch = watch(options.watch, () => {
asyncData.refresh()
})
if (instance) {
onUnmounted(() => unwatch())
}
}
}
// Allow directly awaiting on asyncData