Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
73 changes: 73 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,73 @@
# `useNuxtData`

`useNuxtData` gives you access to the current cached value of `useAsyncData`, `useLazyAsyncData`, `useFetch` and `useLazyFetch` with explicitly provided key.

::Alert
This feature is not released yet. You can beta test using [Edge Channel](https://nuxt.com/docs/guide/going-further/edge-channel).
::

## Type

```ts
useNuxtData<DataT = any> (key: string): { data: Ref<DataT | null> }
```

## 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 [archive.vue]
// We can access same data later using 'posts' key
const { data } = await useFetch('/api/posts', { key: 'posts' })
```

```ts [single.vue]
// Access to the cached value of useFetch in archive.vue
const { data: posts } = useNuxtData('posts')

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 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 [todos.vue]
// We can access same data later using 'todos' key
const { data } = await useFetch('/api/todos', { key: 'todos' })
```

```ts [add-todo.vue]
const newTodo = ref('')
const previousTodos = ref([])

// Access to the cached value of useFetch in todos.vue
const { data: todos } = useNuxtData('todos')

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

todos.value.push(newTodo.value) // Optimistically update the todos.
},
onRequestError () {
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<DataT = any> (key: string): { data: Ref<DataT | null> } {
const nuxt = useNuxtApp()

// Initialize value when key is not already set
if (!(key in nuxt.payload.data)) {
nuxt.payload.data[key] = null
}

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

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