@nuxt/docs-nightly 4.2.1-29360990.b3040970 → 4.2.1-29365059.456cc36c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -194,10 +194,10 @@ The `useAsyncData` composable is a great way to wrap and wait for multiple `$fet
194
194
 
195
195
  ```vue
196
196
  <script setup lang="ts">
197
- const { data: discounts, status } = await useAsyncData('cart-discount', async () => {
197
+ const { data: discounts, status } = await useAsyncData('cart-discount', async (_nuxtApp, { signal }) => {
198
198
  const [coupons, offers] = await Promise.all([
199
- $fetch('/cart/coupons'),
200
- $fetch('/cart/offers'),
199
+ $fetch('/cart/coupons', { signal }),
200
+ $fetch('/cart/offers', { signal }),
201
201
  ])
202
202
 
203
203
  return { coupons, offers }
@@ -372,8 +372,8 @@ The following options **must be consistent** across all calls with the same key:
372
372
 
373
373
  ```ts
374
374
  // ❌ This will trigger a development warning
375
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
376
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
375
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
376
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
377
377
  ```
378
378
 
379
379
  The following options **can safely differ** without triggering warnings:
@@ -385,16 +385,16 @@ The following options **can safely differ** without triggering warnings:
385
385
 
386
386
  ```ts
387
387
  // ✅ This is allowed
388
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
389
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
388
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
389
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
390
390
  ```
391
391
 
392
392
  If you need independent instances, use different keys:
393
393
 
394
394
  ```ts
395
395
  // These are completely independent instances
396
- const { data: users1 } = useAsyncData('users-1', () => $fetch('/api/users'))
397
- const { data: users2 } = useAsyncData('users-2', () => $fetch('/api/users'))
396
+ const { data: users1 } = useAsyncData('users-1', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }))
397
+ const { data: users2 } = useAsyncData('users-2', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }))
398
398
  ```
399
399
 
400
400
  #### Reactive Keys
@@ -804,10 +804,10 @@ while (true) {
804
804
  When requests don't rely on each other, you can make them in parallel with `Promise.all()` to boost performance.
805
805
 
806
806
  ```ts
807
- const { data } = await useAsyncData(() => {
807
+ const { data } = await useAsyncData((_nuxtApp, { signal }) => {
808
808
  return Promise.all([
809
- $fetch('/api/comments/'),
810
- $fetch('/api/author/12'),
809
+ $fetch('/api/comments/', { signal }),
810
+ $fetch('/api/author/12', { signal }),
811
811
  ])
812
812
  })
813
813
 
@@ -234,10 +234,6 @@ declare module 'vue' {
234
234
  export {}
235
235
  ```
236
236
 
237
- ::note
238
- If you are using WebStorm, you may need to augment `@vue/runtime-core` until [this issue](https://youtrack.jetbrains.com/issue/WEB-59818/VUE-TypeScript-WS-PS-does-not-correctly-display-type-of-globally-injected-properties) is resolved.
239
- ::
240
-
241
237
  ## Vue Plugins
242
238
 
243
239
  If you want to use Vue plugins, like [vue-gtag](https://github.com/MatteoGabriele/vue-gtag) to add Google Analytics tags, you can use a Nuxt plugin to do so.
@@ -132,9 +132,9 @@ export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D> (
132
132
 
133
133
  ## Server Types
134
134
 
135
- ::tip
136
- This feature is available from Nuxt >= 3.5
137
- ::
135
+ Auto-imports and other types are different for the `server/` directory, as it is running in a different context from the `app/` directory.
136
+
137
+ By default, Nuxt 4 generates a [`tsconfig.json`](/docs/4.x/guide/directory-structure/tsconfig) which includes a project reference covering the `server/` folder which ensures accurate typings.
138
138
 
139
139
  ## Recipes
140
140
 
@@ -405,12 +405,12 @@ should do this automatically for you.)
405
405
  // This would be unsafe in a dynamic page (e.g. `[slug].vue`) because the route slug makes a difference
406
406
  // to the data fetched, but Nuxt can't know that because it's not reflected in the key.
407
407
  const route = useRoute()
408
- const { data } = await useAsyncData(async () => {
409
- return await $fetch(`/api/my-page/${route.params.slug}`)
408
+ const { data } = await useAsyncData(async (_nuxtApp, { signal }) => {
409
+ return await $fetch(`/api/my-page/${route.params.slug}`, { signal })
410
410
  })
411
411
  // Instead, you should use a key that uniquely identifies the data fetched.
412
- const { data } = await useAsyncData(route.params.slug, async () => {
413
- return await $fetch(`/api/my-page/${route.params.slug}`)
412
+ const { data } = await useAsyncData(route.params.slug, async (_nuxtApp, { signal }) => {
413
+ return await $fetch(`/api/my-page/${route.params.slug}`, { signal })
414
414
  })
415
415
  ```
416
416
 
@@ -18,9 +18,9 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
18
18
 
19
19
  ```vue [app/pages/index.vue]
20
20
  <script setup lang="ts">
21
- const { data, status, error, refresh, clear } = await useAsyncData(
21
+ const { data, status, pending, error, refresh, clear } = await useAsyncData(
22
22
  'mountains',
23
- () => $fetch('https://api.nuxtjs.dev/mountains'),
23
+ (_nuxtApp, { signal }) => $fetch('https://api.nuxtjs.dev/mountains', { signal }),
24
24
  )
25
25
  </script>
26
26
  ```
@@ -30,7 +30,7 @@ If you're using a custom useAsyncData wrapper, do not await it in the composable
30
30
  ::
31
31
 
32
32
  ::note
33
- `data`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
33
+ `data`, `status`, `pending` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
34
34
  ::
35
35
 
36
36
  ### Watch Params
@@ -42,10 +42,11 @@ The built-in `watch` option allows automatically rerunning the fetcher function
42
42
  const page = ref(1)
43
43
  const { data: posts } = await useAsyncData(
44
44
  'posts',
45
- () => $fetch('https://fakeApi.com/posts', {
45
+ (_nuxtApp, { signal }) => $fetch('https://fakeApi.com/posts', {
46
46
  params: {
47
47
  page: page.value,
48
48
  },
49
+ signal,
49
50
  }), {
50
51
  watch: [page],
51
52
  },
@@ -70,6 +71,64 @@ const { data: user } = useAsyncData(
70
71
  </script>
71
72
  ```
72
73
 
74
+ ### Make your `handler` abortable
75
+
76
+ You can make your `handler` function abortable by using the `signal` provided in the second argument. This is useful for cancelling requests when they are no longer needed, such as when a user navigates away from a page. `$fetch` natively supports abort signals.
77
+
78
+ ```ts
79
+ const { data, error } = await useAsyncData(
80
+ 'users',
81
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
82
+ )
83
+
84
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
85
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
86
+ refresh()
87
+
88
+ clear() // will cancel the latest pending handler
89
+ ```
90
+
91
+ You can also pass an `AbortSignal` to the `refresh`/`execute` function to cancel individual requests manually.
92
+
93
+ ```ts
94
+ const { refresh } = await useAsyncData(
95
+ 'users',
96
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
97
+ )
98
+ let abortController: AbortController | undefined
99
+
100
+ function handleUserAction () {
101
+ abortController = new AbortController()
102
+ refresh({ signal: abortController.signal })
103
+ }
104
+
105
+ function handleCancel () {
106
+ abortController?.abort() // aborts the ongoing refresh request
107
+ }
108
+ ```
109
+
110
+ If your `handler` function does not support abort signals, you can implement your own abort logic using the `signal` provided.
111
+
112
+ ```ts
113
+ const { data, error } = await useAsyncData(
114
+ 'users',
115
+ (_nuxtApp, { signal }) => {
116
+ return new Promise((resolve, reject) => {
117
+ signal?.addEventListener('abort', () => {
118
+ reject(new Error('Request aborted'))
119
+ })
120
+ return Promise.resolve(callback.call(this, yourHandler)).then(resolve, reject)
121
+ })
122
+ },
123
+ )
124
+ ```
125
+
126
+ The handler signal will be aborted when:
127
+
128
+ - A new request is made with `dedupe: 'cancel'`
129
+ - The `clear` function is called
130
+ - The `options.timeout` duration is exceeded
131
+
73
132
  ::warning
74
133
  [`useAsyncData`](/docs/4.x/api/composables/use-async-data) is a reserved function name transformed by the compiler, so you should not name your own function [`useAsyncData`](/docs/4.x/api/composables/use-async-data).
75
134
  ::
@@ -116,7 +175,7 @@ You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `u
116
175
 
117
176
  ### Shared State and Option Consistency
118
177
 
119
- When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error` and `status` refs. This ensures consistency across components but requires option consistency.
178
+ When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error`, `status` and `pending` refs. This ensures consistency across components but requires option consistency.
120
179
 
121
180
  The following options **must be consistent** across all calls with the same key:
122
181
  - `handler` function
@@ -135,12 +194,12 @@ The following options **can differ** without triggering warnings:
135
194
 
136
195
  ```ts
137
196
  // ❌ This will trigger a development warning
138
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
139
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
197
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
198
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
140
199
 
141
200
  // ✅ This is allowed
142
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
143
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
201
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
202
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
144
203
  ```
145
204
 
146
205
  ::tip
@@ -159,6 +218,7 @@ Keyed state created using `useAsyncData` can be retrieved across your Nuxt appli
159
218
  - `pending`: the request is in progress
160
219
  - `success`: the request has completed successfully
161
220
  - `error`: the request has failed
221
+ - `pending`: a `Ref<boolean>` that is `true` while the request is in progress (that is, while `status.value === 'pending'`).
162
222
  - `clear`: a function that can be used to set `data` to `undefined` (or the value of `options.default()` if provided), set `error` to `undefined`, set `status` to `idle`, and mark any currently pending requests as cancelled.
163
223
 
164
224
  By default, Nuxt waits until a `refresh` is finished before it can be executed again.
@@ -170,13 +230,15 @@ If you have not fetched data on the server (for example, with `server: false`),
170
230
  ## Type
171
231
 
172
232
  ```ts [Signature]
233
+ export type AsyncDataHandler<ResT> = (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<ResT>
234
+
173
235
  export function useAsyncData<DataT, DataE> (
174
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
236
+ handler: AsyncDataHandler<DataT>,
175
237
  options?: AsyncDataOptions<DataT>
176
238
  ): AsyncData<DataT, DataE>
177
239
  export function useAsyncData<DataT, DataE> (
178
240
  key: MaybeRefOrGetter<string>,
179
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
241
+ handler: AsyncDataHandler<DataT>,
180
242
  options?: AsyncDataOptions<DataT>
181
243
  ): Promise<AsyncData<DataT, DataE>>
182
244
 
@@ -206,6 +268,7 @@ type AsyncData<DataT, ErrorT> = {
206
268
  clear: () => void
207
269
  error: Ref<ErrorT | undefined>
208
270
  status: Ref<AsyncDataRequestStatus>
271
+ pending: Ref<boolean>
209
272
  }
210
273
 
211
274
  interface AsyncDataExecuteOptions {
@@ -108,7 +108,7 @@ Nuxt exposes the following properties through `ssrContext`:
108
108
  ::code-group
109
109
  ```vue [app/app.vue]
110
110
  <script setup lang="ts">
111
- const { data } = await useAsyncData('count', () => $fetch('/api/count'))
111
+ const { data } = await useAsyncData('count', (_nuxtApp, { signal }) => $fetch('/api/count', { signal }))
112
112
  </script>
113
113
  ```
114
114
  ```ts [server/api/count.ts]
@@ -67,7 +67,7 @@ Optimistic Updates is a technique where the user interface is updated immediatel
67
67
  ```vue [app/pages/todos.vue]
68
68
  <script setup lang="ts">
69
69
  // We can access same data later using 'todos' key
70
- const { data } = await useAsyncData('todos', () => $fetch('/api/todos'))
70
+ const { data } = await useAsyncData('todos', (_nuxtApp, { signal }) => $fetch('/api/todos', { signal }))
71
71
  </script>
72
72
  ```
73
73
 
@@ -33,7 +33,7 @@ const { data: forwarded } = await useAsyncData(() => requestFetch('/api/cookies'
33
33
 
34
34
  // This will NOT forward anything
35
35
  // Result: { cookies: {} }
36
- const { data: notForwarded } = await useAsyncData(() => $fetch('/api/cookies'))
36
+ const { data: notForwarded } = await useAsyncData((_nuxtApp, { signal }) => $fetch('/api/cookies', { signal }))
37
37
  </script>
38
38
  ```
39
39
 
@@ -36,7 +36,7 @@ const loggedIn = computed(() => !!tokenCookie.value)
36
36
  ```
37
37
 
38
38
  ::note{to="/docs/4.x/guide/going-further/experimental-features#cookiestore"}
39
- You can enable experimental `cookieStore` option to automatically refresh `useCookie` value when cookie changes in the browser.
39
+ Since [Nuxt v3.12.0](https://github.com/nuxt/nuxt/releases/tag/v3.12.0), the experimental `cookieStore` option is enabled by default. It automatically refreshes the `useCookie` value when cookies change in the browser.
40
40
  ::
41
41
 
42
42
  ## Type
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/docs-nightly",
3
- "version": "4.2.1-29360990.b3040970",
3
+ "version": "4.2.1-29365059.456cc36c",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",