Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.

feat: useNuxtData composable #9262

Merged
merged 25 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions docs/content/1.docs/3.api/1.composables/use-nuxt-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# `useNuxtData`

`useNuxtData` gives you access to the cache of `useAsyncData`, `useLazyAsyncData`, `useFetch` and `useLazyFetch`.

## Type

```ts
useNuxtData<T = any> (key: string): Ref<T>
useNuxtData():β€Œ Ref<Recod<string, any>>
```

## Examples

### Show stale data while fetching in the background

The example below shows how you can use cached data as a placeholder while the most recent data is being fetched from the server.

```ts
// In Archive.vue
const { data } = await useFetch('/api/posts', {
key: 'posts', // You need to set a key to access the data later.
})
```

```ts
// In Single.vue
const { data } = await useFetch(`/api/posts/${postId}`, {
key: `post-${postId}`,
default: () => {
// Find the individual post from the cache and set it as the default value.
return useNuxtData('posts').value.find(post => post.id === postId)
}
})
```

### Optimistic Updates

We can leverage the cache to update the UI after a mutation, while the data is being invalidated in the background.

```ts
// In Todos.vue
const { data } = await useFetch('/api/todos', {
key: 'todos'
})
```

```ts
// In AddTodo.vue
const newTodo = ref('')
const previousTodos = ref([])

const { data } = await useFetch('/api/addTodo', {
key: 'addTodo',
method: 'post',
body: {
todo: newTodo.value
},
onRequest () {
previousTodos.value = useNuxtData('todos').value // Store the previously cached value to restore if fetch fails.

useNuxtData('todos').value.push(newTodo.value) // Optimistically update the todos.
},
onRequestError () {
useNuxtData('todos').value = previousTodos.value // Rollback the data if the request failed.
},
async onResponse () {
await refreshNuxtData('todos') // Invalidate todos in the background if the request succeeded.
}
})
```
15 changes: 14 additions & 1 deletion packages/nuxt/src/app/composables/asyncData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance, watch, unref } from 'vue'
import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance, watch, unref, toRef } from 'vue'
import type { Ref, WatchSource } from 'vue'
import { NuxtApp, useNuxtApp } from '../nuxt'
import { createError } from './error'
Expand Down Expand Up @@ -268,6 +268,19 @@ export function useLazyAsyncData<
return useAsyncData(key, handler, { ...options, lazy: true }, null)
}

export function useNuxtData<T = any> (key: string): Ref<T>
export function useNuxtData (): Ref<Record<string, any>>
export function useNuxtData (key?: string): unknown {
const nuxt = useNuxtApp()

// initialize value when key is not already set
if (key && nuxt.payload.data[key] === undefined) {
nuxt.payload.data[key] = null
}

return key ? toRef(nuxt.payload.data, key) : ref(nuxt.payload.data)
}

export async function refreshNuxtData (keys?: string | string[]): Promise<void> {
if (process.server) {
return Promise.resolve()
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { defineNuxtComponent } from './component'
export { useAsyncData, useLazyAsyncData, refreshNuxtData, clearNuxtData } from './asyncData'
export { useAsyncData, useLazyAsyncData, useNuxtData, refreshNuxtData, clearNuxtData } from './asyncData'
export type { AsyncDataOptions, AsyncData } from './asyncData'
export { useHydration } from './hydrate'
export { useState } from './state'
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/src/imports/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const appPreset = defineUnimportPreset({
imports: [
'useAsyncData',
'useLazyAsyncData',
'useNuxtData',
'refreshNuxtData',
'clearNuxtData',
'defineNuxtComponent',
Expand Down