Data Fetching
In Nuxt we have 2 ways of getting data from an API. We can use the fetch method or the asyncData method.
Nuxt supports traditional Vue patterns for loading data in your client-side app, such as fetching data in a component's mounted() hook. Universal apps, however, need to use Nuxt-specific hooks to be able to render data during server-side rendering. This allows your page to render with all of its required data present.
Nuxt has two hooks for asynchronous data loading:
-
asyncData. This hook can only be placed on page components. Unlikefetch, this hook does not display a loading placeholder during client-side rendering: instead, this hook blocks route navigation until it is resolved, displaying a page error if it fails. -
fetch(Nuxt 2.12+). This hook can be placed on any component, and provides shortcuts for rendering loading states (during client-side rendering) and errors.
These hooks can be used with any data fetching library you choose. We recommend using @nuxt/http or @nuxt/axios for making requests to HTTP APIs. More information about these libraries, such as guides for configuring authentication headers, can be found in their respective documentation.
fetch or asyncData inside a mixin and also have it defined in a component/page, the mixin function will be overwritten instead of called.The fetch hook
fetch hook that only worked for page components and didn't have access to the component instance.If your fetch() accepts a context argument, it will be treated like a legacy fetch hook. This functionality is deprecated, and should be replaced with either asyncData or an anonymous middleware. fetch is a hook called during server-side rendering after the component instance is created, and on the client when navigating. The fetch hook should return a promise (whether explicitly, or implicitly using async/await) that will be resolved:
- On the server, before the initial page is rendered
- On the client, some time after the component is mounted
Usage
Fetching data
Within the fetch hook, you will have access to the component instance via this.
data(). Then the data that comes from the fetch can be assigned to these properties.Changing fetch behavior
fetchOnServer: Boolean or Function (default: true), call fetch() when server-rendering the page
fetchKey: String or Function (defaults to the component scope ID or component name), a key (or a function that produces a unique key) that identifies the result of this component's fetch (available on Nuxt 2.15+). When hydrating a server-rendered page, this key is used to map the result of the server-side fetch() to the client-side component data. More information available in original PR .
fetchDelay: Integer (default: 200), set the minimum executing time in milliseconds (to avoid quick flashes)
When fetchOnServer is falsy (false or returns false), fetch will be called only on client-side and $fetchState.pending will return true when server-rendering the component.
export default {
data: () => ({
posts: []
}),
async fetch() {
this.posts = await this.$http.$get('https://api.nuxtjs.dev/posts')
},
fetchOnServer: false,
// multiple components can return the same `fetchKey` and Nuxt will track them both separately
fetchKey: 'site-sidebar',
// alternatively, for more control, a function can be passed with access to the component instance
// It will be called in `created` and must not depend on fetched data
fetchKey(getCounter) {
// getCounter is a method that can be called to get the next number in a sequence
// as part of generating a unique fetchKey.
return this.someOtherData + getCounter('sidebar')
}
}
Accessing the fetch state
The fetch hook exposes this.$fetchState at the component level with the following properties:
-
pendingis aBooleanthat allows you to display a placeholder whenfetchis being called on client-side. -
erroris eithernullor anErrorthrown by the fetch hook -
timestampis a timestamp of the last fetch, useful for caching withkeep-alive
In addition to fetch being called by Nuxt, you can manually call fetch in your component (to e.g. reload its async data) by calling this.$fetch().
<template>
<div>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt Mountains</h1>
<ul>
<li v-for="mountain of mountains">{{ mountain.title }}</li>
</ul>
<button @click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
this.$nuxt.context.Listening to query string changes
The fetch hook is not called on query string changes by default. To watch for query changes you can add a watcher on $route.query and call $fetch:
export default {
watch: {
'$route.query': '$fetch'
},
async fetch() {
// Called also on query changes
}
}
Caching
You can use keep-alive directive in <nuxt/> and <nuxt-child/> component to save fetch calls on pages you already visited:
<template>
<nuxt keep-alive />
</template>
You can also specify the props passed to <keep-alive> by passing a prop keep-alive-props to the <nuxt> component.
<nuxt keep-alive :keep-alive-props="{ max: 10 }" />
Keeps only 10 page components in memory.
Error handling
redirect or error methods within fetch(). Instead, you will need to handle it within your component using $fetchState.error.We can check $fetchState.error and show an error message if there is an error fetching the data.
<template>
<div>
<p v-if="$fetchState.pending">Loading....</p>
<p v-else-if="$fetchState.error">Error while fetching mountains</p>
<ul v-else>
<li v-for="(mountain, index) in mountains" :key="index">
{{ mountain.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
Using activated hook
Nuxt will directly fill this.$fetchState.timestamp (timestamp) of the last fetch call (ssr included). You can use this property combined with activated hook to add a 30 seconds cache to fetch:
<template> ... </template>
<script>
export default {
data() {
return {
posts: []
}
},
activated() {
// Call fetch again if last fetch more than 30 sec ago
if (this.$fetchState.timestamp <= Date.now() - 30000) {
this.$fetch()
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
}
}
</script>
The navigation to the same page will not call fetch if last fetch call was before 30 sec ago.
Async Data
asyncData is another hook for universal data fetching. Unlike fetch, which requires you to set properties on the component instance (or dispatch Vuex actions) to save your async state, asyncData simply merges its return value into your component's local state. Here's an example using the @nuxt/http library:
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>
<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>
Unlike fetch, the promise returned by the asyncData hook is resolved during route transition. This means that no "loading placeholder" is visible during client-side transitions (although the loading bar can be used to indicate a loading state to the user). Nuxt will instead wait for the asyncData hook to be finished before navigating to the next page or display the error page ).
This hook can only be used for page-level components. Unlike fetch, asyncData cannot access the component instance (this). Instead, it receives the context as its argument. You can use it to fetch some data and Nuxt will automatically shallow merge the returned object with the component data.
In the upcoming examples, we are using @nuxt/http which we recommend for fetching data from an API.
Async data in components?
Because components do not have an asyncData method, you cannot directly fetch async data server side within a component. In order to get around this limitation you have three basic options:
-
Use the new
fetchhook that is available in Nuxt 2.12 and later versions. -
Make the API call in the
mountedhook and set data properties when loaded. Downside: Won't work for server side rendering. -
Make the API call in the
asyncDatamethod of the page component and pass the data as props to the sub components. Server rendering will work fine. Downside: theasyncDataof the page might be less readable because it's loading the data for other components.
Listening to query changes
The asyncData method is not called on query string changes by default. If you want to change this behavior, for example when building a pagination component, you can set up parameters that should be listened to with the watchQuery property of your page component.
watchQuery won't work properly for static generated sites. To get this working use the fetch hook and listen to query string changes .
Sébastien Chopin
Nazaré da Piedade
Nobu
川音리오
Maciek Palmowski
Nestor Vera
Daniel Roe
Yue Yang
Jeronimas
Clément Ollivier
Alexander Lichter
N3-rd
Adrien Zaganelli
Mag
Stefan Huber
Olga Bulat
Paiva
Florian Reuschel
Savas Vedova
HIJACK
Vinícius Alves
Kareem Dabbeet
Valentín Costa
Ryan Skinner
Alex Hirzel
Ajeet Chaulagain
René Eschke
Nico Devs
Muhammad
Naoki Hamada
Tom
Yann Aufray
Anthony Chu
Nuzhat Minhaz
Lucas Portet
Richard Schloss
Bobby
bpy
Antony Konstantinidis
Hibariya
Jose Seabra
Eze
Florian Lefebvre
Lucas Recoaro
Julien SEIXAS