useFetch, useAsyncData, and $fetch.
Overview
In a nutshell:$fetchis the simplest way to make a network requestuseFetchis a wrapper around$fetchthat fetches data only once in universal renderinguseAsyncDatais similar touseFetchbut offers more fine-grained control
useFetch and useAsyncData share a common set of options and patterns.
Why useFetch and useAsyncData?
Nuxt is a framework that can run isomorphic (or universal) code in both server and client environments. If the$fetch function is used to perform data fetching in the setup function of a Vue component, this may cause data to be fetched twice: once on the server (to render the HTML) and once again on the client (when the HTML is hydrated).
The useFetch and useAsyncData composables solve this problem by ensuring that if an API call is made on the server, the data is forwarded to the client in the payload.
The payload is a JavaScript object accessible through useNuxtApp().payload. It’s used on the client to avoid refetching the same data when the code is executed in the browser during hydration.
app/app.vue
useFetch ensures that the request occurs on the server and is properly forwarded to the browser. $fetch has no such mechanism and is better suited for requests made solely from the browser.
Using $fetch
Nuxt includes the ofetch library, auto-imported as the$fetch alias globally across your application.
pages/todos.vue
Using useFetch
TheuseFetch composable uses $fetch under the hood to make SSR-safe network calls in the setup function.
app/app.vue
useAsyncData composable and $fetch utility, providing a convenient way to fetch data with automatic SSR handling.
Using useAsyncData
TheuseAsyncData composable is responsible for wrapping async logic and returning the result once it’s resolved.
There are cases when using useFetch is not appropriate, for example when a CMS or third-party provides their own query layer. In this case, you can use useAsyncData to wrap your calls.
app/pages/users.vue
The first argument of
useAsyncData is a unique key used to cache the response of the second argument. This key can be ignored by directly passing the querying function, and the key will be auto-generated. Setting a key can be useful to share the same data between components or to refresh specific data.Handling Multiple Requests
TheuseAsyncData composable is a great way to wrap and wait for multiple $fetch requests to be completed, and then process the results.
Return Values
useFetch and useAsyncData have the same return values:
data- The result of the asynchronous function that is passed inrefresh/execute- A function that can be used to refresh the data returned by the handler functionclear- A function to setdatatoundefined, seterrortoundefined, setstatustoidle, and mark any pending requests as cancellederror- An error object if the data fetching failedstatus- A string indicating the status of the data request ("idle","pending","success","error")
data, error, and status are Vue refs accessible with .value in <script setup>.Common Options
Lazy Fetching
By default, data fetching composables wait for the resolution of their asynchronous function before navigating to a new page. You can ignore this behavior on client-side navigation with thelazy option.
app/app.vue
useLazyFetch and useLazyAsyncData as convenient methods to perform the same.
Client-Only Fetching
By default, data fetching composables perform their asynchronous function on both client and server environments. Set theserver option to false to only perform the call on the client-side.
Caching and Refetching
useFetch and useAsyncData use keys to prevent refetching the same data:
useFetchuses the provided URL as a key. Alternatively, akeyvalue can be provided in the options objectuseAsyncDatauses its first argument as a key if it’s a string
watch option to re-run your fetching function each time other reactive values change:
Computed URL
You can compute a URL from reactive values, and Nuxt will automatically use the reactive value and re-fetch each time it changes.Best Practices
- Use
useFetchfor fetching data in component setup - Use
$fetchfor event handlers and client-side operations - Use
useAsyncDatawhen you need fine-grained control or are wrapping custom fetching logic - Always handle loading and error states in your templates