How to handle Nuxt.js asyncData with new composition API

by mmyoji

2 min read

[UPDATED: 2021-03-30]

We already have @nuxtjs/composition-api. It has useAsync function for the purpose.


Vue.js will introduce new composition API (a.k.a. function API). It's really great API but I wonder how to combine with Nuxt.js asyncData w/ this new API. I find solutions and write about it though Nuxt.js might change its APIs.

A1. Use fetch and Vuex

First, I thought I would use composition API's onBeforeMount or onCreated (you know onCreated API doesn't exist) inside setup.

BUT, asyncData is not in Vue.js lifecycle. It's a kind of vue-router's feature I guess. The API fetches data when URI path changes and Nuxt.js will render(or create) next page vm after fetching the data.

And if you use TypeScript, accessing this inside vm is not good for it. I don't like to write @ts-ignore for the purpose.

So you can utilize context arguments both fetch (Nuxt.js) and setup (composition API).

Then, when you want the web page behavior as the same, you use fetch instead of asyncData and set the data in Vuex store through the context. Nuxt.js includes Vuex and you don't need to install additional packages. ref

The sample code is like this: (the code is just an example, I haven't tried this yet)

// inside <script lang="ts"> of pages/foo.vue
import { createComponent, ref } from '@vue/composition-api'

export default createComponent({
  async fetch({ store }) {
    const res = await axios.get('http://my-api/stars')
    store.commit('setStars', res.data)
  }

  setup(props, { root }) {
    const store = root.$store
    const stars = ref<Star[]>(store.state.stars)

    return {
      stars
    }
  }
})

I think this is better solution for the question.

A2. Use loading view

This is more general and simpler approach.

Prepare loader view and fetch data inside Vue.js lifecycle and show expected view after data is fetched.