--- navigation.icon: uil:channel description: Nuxt provides composables to handle data fetching within your application. --- # Data Fetching Nuxt provides useFetch, useLazyFetch, useAsyncData and useLazyAsyncData to handle data fetching within your application. ::alert{icon=๐Ÿ‘‰} **`useFetch`, `useLazyFetch`, `useAsyncData` and `useLazyAsyncData` only work during `setup` or `Lifecycle Hooks`** :: ## `useFetch` Within your pages, components and plugins you can use `useFetch` to universally fetch from any URL. This composable provides a convenient wrapper around `useAsyncData` and `$fetch`. It automatically generates a key based on URL and fetch options, provides type hints for request url based on server routes, and infers API response type. ::ReadMore{link="/docs/api/composables/use-fetch"} :: ### Example ```vue [app.vue] ``` ::LinkExample{link="/docs/examples/composables/use-fetch"} :: ## `useLazyFetch` This composable behaves identically to `useFetch` with the `lazy: true` option set. In other words, the async function does not block navigation. That means you will need to handle the situation where the data is `null` (or whatever value you have provided in a custom `default` factory function). ::ReadMore{link="/docs/api/composables/use-lazy-fetch"} :: ### Example ```vue ``` ## `useAsyncData` Within your pages, components and plugins you can use `useAsyncData` to get access to data that resolves asynchronously. ::alert You might be asking yourself: what is the difference between `useFetch` and `useAsyncData`? In brief, `useFetch` receives a URL and gets that data, whereas `useAsyncData` might have more complex logic. `useFetch(url)` is nearly equivalent to `useAsyncData(url, () => $fetch(url))` - it's developer experience sugar for the most common use case. :: ::ReadMore{link="/docs/api/composables/use-async-data"} :: ### Example ```ts [server/api/count.ts] let counter = 0 export default defineEventHandler(() => { counter++ return counter }) ``` ```vue [app.vue] ``` ::LinkExample{link="/docs/examples/composables/use-async-data"} :: ## `useLazyAsyncData` This composable behaves identically to `useAsyncData` with the `lazy: true` option set. In other words, the async function does not block navigation. That means you will need to handle the situation where the data is `null` (or whatever value you have provided in a custom `default` factory function). ::ReadMore{link="/docs/api/composables/use-lazy-async-data"} :: ### Example ```vue ``` ## Refreshing Data Sometimes throughout the course of your user's page visit, you may need to refresh the data loaded from the API. This can happen if the user chooses to paginate, filter results, search, etc. You can make use of the `refresh()` method returned from the `useFetch()` composable to refresh the data with different query parameters: ```vue ``` The key to making this work is to call the `refresh()` method returned from the `useFetch()` composable when a query parameter has changed. By default, `refresh()` will cancel any pending requests their result will not update the data or pending state. Any previously awaited promises will not resolve until this new request resolves. You can prevent this behaviour by setting the `dedupe` option, which will instead return the promise for the currently-executing request, if there is one. ```js refresh({ dedupe: true }) ``` ### `refreshNuxtData` Invalidate the cache of `useAsyncData`, `useLazyAsyncData`, `useFetch` and `useLazyFetch` and trigger the refetch. This method is useful if you want to refresh all the data fetching for a current page. ::ReadMore{link="/docs/api/utils/refresh-nuxt-data"} :: #### Example ```vue ``` ### `clearNuxtData` Delete cached data, error status and pending promises of `useAsyncData` and `useFetch`. This method is useful if you want to invalidate the data fetching for another page. ::ReadMore{link="/docs/api/utils/clear-nuxt-data"} :: ## Options API support Nuxt 3 provides a way to perform `asyncData` fetching within the Options API. You must wrap your component definition within `defineNuxtComponent` for this to work. ```vue ``` ::Alert Using ` ``` ::alert{type="warning"} Be very careful before proxying headers to an external API and just include headers that you need. Not all headers are safe to be bypassed and might introduce unwanted behavior. Here is a list of common headers that are NOT to be proxied: * `host`, `accept` * `content-length`, `content-md5`, `content-type` * `x-forwarded-host`, `x-forwarded-port`, `x-forwarded-proto` * `cf-connecting-ip`, `cf-ray` :: #### Example: Pass Cookies From Server-side API Calls on SSR Response If you want to pass on/proxy cookies in the other direction, from an internal request back to the client, you will need to handle this yourself. ```ts [composables/fetch.ts] export const fetchWithCookie = async (event: H3Event, url: string) => { const res = await $fetch.raw(url) const cookies = (res.headers.get('set-cookie') || '').split(',') for (const cookie of cookies) { appendHeader(event, 'set-cookie', cookie) } return res._data } ``` ```vue ``` ## Best Practices ### Minimize Payload The data returned by these composables will be stored inside the page payload. This means that every key returned that is not used in your component will be added to the payload. ::alert{icon=๐Ÿ‘‰} **We strongly recommend you only select the keys that you will use in your component.** :: Imagine that `/api/mountains/everest` returns the following object: ```json { "title": "Mount Everest", "description": "Mount Everest is Earth's highest mountain above sea level, located in the Mahalangur Himal sub-range of the Himalayas. The Chinaโ€“Nepal border runs across its summit point", "height": "8,848 m", "countries": [ "China", "Nepal" ], "continent": "Asia", "image": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Everest_kalapatthar.jpg/600px-Everest_kalapatthar.jpg" } ``` If you plan to only use `title` and `description` in your component, you can select the keys by chaining the result of `$fetch` or `pick` option: ```vue ``` ### Avoid double calls Calling `$fetch` in code that is executed on both server and client (such as in the top level of a `setup` function) will fetch the data twice - initially on the server and then again on the client during the hydration phase. This is because `$fetch` does not automatically serialize or transfer the data to the client. For example: **/pages/price.vue**: Isomorphic code below executes `$fetch` twice (initially on the server, then again on the client). ```ts ``` **/server/api/product.get.ts**: Server only code below executes `$fetch` only once at the server side. ```ts export default eventHandler(async (event: H3Event) => { const price = $fetch('/api/price'); return { color: getColor(), price }; }); ``` If fetching twice isn't your intended behavior, to fetch only on the server side and transfer it to the client, wrap `$fetch` with `useAsyncData()` or use `useFetch()`. ```ts ``` ## Using Async Setup If you are using `async setup()`, the current component instance will be lost after the first `await`. (This is a Vue 3 limitation.) If you want to use multiple async operations, such as multiple calls to `useFetch`, you will need to use ` ``` ## Serialization When fetching data from the `server` directory, the response is serialized using `JSON.stringify`. However, since serialization is limited to only JavaScript primitive types, Nuxt does its best to convert the return type of `$fetch` and `useFetch` to match the actual value. ::alert{icon=๐Ÿ‘‰} You can learn more about `JSON.stringify` limitations [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description). :: ### Example ```ts [server/api/foo.ts] export default defineEventHandler(() => { return new Date() }) ``` ```vue [app.vue] ``` ### Custom serializer function To customize the serialization behavior, you can define a `toJSON` function on your returned object. If you define a `toJSON` method, Nuxt will respect the return type of the function and will not try to convert the types. ```ts [server/api/bar.ts] export default defineEventHandler(() => { const data = { createdAt: new Date(), toJSON() { return { createdAt: { year: this.createdAt.getFullYear(), month: this.createdAt.getMonth(), day: this.createdAt.getDate(), }, } }, } return data }) ``` ```vue [app.vue] ``` ### Using an alternative serializer Nuxt does not currently support an alternative serializer to `JSON.stringify`. However, you can return your payload as a normal string and utilize the `toJSON` method to maintain type safety. In the example below, we use [superjson](github.com/blitz-js/superjson) as our serializer. ```ts [server/api/superjson.ts] import superjson from 'superjson' export default defineEventHandler(() => { const data = { createdAt: new Date(), // Workaround the type conversion toJSON() { return this } } // Serialize the output to string, using superjson return superjson.stringify(data) as unknown as typeof data }) ``` ```vue [app.vue] ```