Nuxt comes with two composables and a built-in library to perform data-fetching in browser or server environments: `useFetch`, `useAsyncData` and `$fetch` .
If you need more fine-grained control, you can use `useAsyncData` and `$fetch` independently.
The two composables share a common set of options and patterns that we will detail in the last sections.
## Why using specific composables?
When using a framework like Nuxt that can perform calls and render pages on both client and server environments, some challenges must be addressed. This is why Nuxt provides composables to wrap your queries.
The `useFetch` and `useAsyncData` composables ensure that once an API call is made on the server, the data is properly forwarded to the client in the payload. This JavaScript object is accessible through [`useNuxtApp().payload`](/docs/api/composables/use-nuxt-app#payload) and is used on the client to avoid refetching the same data when the code is executed in the browser.
Nuxt uses Vue’s `<Suspense>` component under the hood to prevent navigation before every async data is available to the view. The data fetching composables can help you leverage this feature and use what suits best on a per-calls basis.
::alert{icon=👉}
These composables are auto-imported and can be used in `setup` functions or lifecycle hooks
Beware that using only `$fetch` will not provide the benefits described in [the first section of this page](#why-using-specific-composables). It is recommended to use `$fetch` when posting data to an event handler, when doing client-side only logic, or combined with `useAsyncData`.
`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.
There are some cases when using the `useFetch` composable is not appropriate, for example when a CMS or a third-party provide their own query layer. In this case, you can use `useAsyncData` to wrap your calls and still keep the benefits provided by the composable:
The first argument of `useAsyncData` is the unique key used to cache the response of the second argument, the querying function. This argument can be ignored by directly passing the querying function. In that case, it will be auto-generated.
`useAsyncData` and `useFetch` return the same object type and accept a common set of options as their last argument. They can help you control the composables behavior, such as navigation blocking, caching or execution.
By default, data fetching composables will wait for the resolution of their asynchronous function before navigating to a new page by using Vue’s Suspense. This feature can be ignored on client-side navigation with the `lazy` option. In that case, you will have to manually handle loading state using the `pending` value.
By default, data fetching composables will perform their asynchronous function on both client and server environments. Set the `server` option to `false` to only perform the call on the client-side. Combined with the `lazy` option, this can be useful for data that are not needed on the first render (for example, non-SEO sensitive data).
```ts
/* This call will only be performed on the client */
The `pick` option helps you to minimize the payload size stored in your HTML document by only selecting the fields that you want returned from the composables.
-`useFetch` uses the provided URL as a key. Alternatively, a `key` value can be provided in the `options` object passed as a last argument.
-`useAsyncData` uses its first argument as a key if it is a string. If the first argument is the handler function that performs the query, then a key that is unique to the file name and line number of the instance of`useAsyncData`will be generated for you.
If you want to fetch or refresh data manually, use the `execute` or `refresh` function provided by the composables. (`execute` is an alias for `refresh` that works in exactly the same way but is more semantic for cases when `immediate: false`).
To globally refetch or invalidate cached data, see [`clearNuxtData`](/docs/api/utils/clear-nuxt-data) and [`refreshNuxtData`](/docs/api/utils/refresh-nuxt-data).
When we call `$fetch` in the browser, user headers like `cookie` will be directly sent to the API. But during server-side-rendering, since the `$fetch` request takes place 'internally' within the server, it doesn't include the user's browser cookies, nor does it pass on cookies from the fetch response.
The example below adds the request headers to an isomorphic `$fetch` call to ensure that the API endpoint has access to the same `cookie` header originally sent by the user.
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:
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.
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]
<scriptsetuplang="ts">
// Type of `data` is inferred as string even though we returned a Date object
const { data } = await useFetch('/api/foo')
</script>
```
### 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]
<scriptsetuplang="ts">
// Type of `data` is inferred as
// {
// createdAt: {
// year: number
// month: number
// day: number
// }
// }
const { data } = await useFetch('/api/bar')
</script>
```
### 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.