simon
simon

Reputation: 2377

VueJs Async Api Data best practice

I am building a headless SPA SSR in NuxtJs, and I am wondering what best practices is for making sure that the application only loads if connection has been established to the remote API.

This is currently my index.vue component:

<template>
<div class="wrapper">
  <div class="content">
    <div class="title">
      <h1>{{site.meta.title}}</h1>
    </div>
  </div>
</div>
</template>

<script>
import Meta from '../classes/api/General/Meta'

export default {
  data () {
    return {
      meta: null
    }
  },
  created () {
    Meta.getMeta().then((response) => {
      this.meta = response.data
    })
  }
}
</script>

This sometimes resolves in that site.meta.title is undefined because the site is loading before the api data has been initialised. And yes, site.meta.title is defined under the hood in the api. So. Next step I was thinking was using async like following script:

<script>
import Meta from '../classes/api/General/Meta'

export default {
  data () {
    return {
      meta: null
    }
  },
  async created () {
    await Meta.getMeta().then((response) => {
      this.meta = response.data
      console.log(response.data.site.logo)
    })
  }
}
</script>

Though this doesn't help anyway.

But with v-if="meta" it does help. Though: now it seems that Axios is not rendering the content in the code (ssr) anymore.

Upvotes: 0

Views: 2246

Answers (2)

simon
simon

Reputation: 2377

So, It turns out that I got this the completely wrong way around. In the newest nuxt versions, async fetch method is now included (build in).

With this, all rendering etc works fine and as expected. My ended working code looks like this now:

<script>
export default {
  async fetch () {
    this.meta = await fetch(
      'https://testurl.com/meta'
    ).then(res => res.json())
  },
  data () {
    return {
      meta: null
    }
  }
}
</script>

And the beauty with fetch, is that you can add listeners" like so:

<p v-if="$fetchState.pending">Fetching site</p>
<p v-else-if="$fetchState.error">Error happened</p>
<p>This content will be rendered server side even though waiting time</p>

I'm just posting this because my original question was a bit miss explained, and hope to help somebody else.

Edit: I have marked kissu as answer (did see the post after i created this one), because it was explained so nice and well done! Thanks :-)

Upvotes: 1

kissu
kissu

Reputation: 46676

console.log is not something that you can really trust 100% of the time for async debugging tbh.
console.log(JSON.parse(JSON.stringify())) can help a bit more but it's still have some drawbacks sometimes.

As for best practices, both beforeCreate and created do run on both sides (server + client) so it's fine to use those. You can also use asyncData and the new fetch (it's a Nuxt hook, not the actual fetch API).

Beware of using the async/await syntax properly tho (no need for then here):

async created() {
  const response = await Meta.getMeta()
  this.meta = response.data
  console.log(this.meta)
}

Also, with proper async/await, this one will never happen actually

because the site is loading before the api data has been initialised

You can read a bit more about the Nuxt lifecycle here: https://nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle

I'd recommend usually going the async fetch() way (non blocking, nice helpers), or async asyncData() if you need a blocking method. Middlewares can also be useful to make the whole process more flexible around your application.

You can get the whole explanation between the differences of fetch vs asyncData here: https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12/

And if you want to have an example on how to use fetch in a real world scenario, you can read this one: https://nuxtjs.org/blog/build-dev-to-clone-with-nuxt-new-fetch/

Upvotes: 3

Related Questions