How to use the new Fetch in Nuxt.js

Samuel Snopko

Samuel Snopko

Sep 7, 2020
4 min read
Share on Twitter or LinkedIn

It was back in the March (March 17th to be exact), when the Nuxt.js team introduced version 2.12 and the new Fetch hook. This step made it possible to create better architecture for our Nuxt projects.

You may wonder what I am talking about. The fetch was there the whole time... or was it? Yes it was, but in version 2.12 you can now define the fetch hook on the component, which is much cleaner than before. I will cover the difference between the old and new fetch in another article.

Imagine you have a simple component which should show multiple teasers of the articles. In the headless CMS (Storyblok in my case) you could select the articles using the multiselect, like in this example.

The articles are usually content types on their own. They used to live in a separate folder and have a pretty rich content. Because of this the JSON response of this story will not contain the content of the articles, but the IDs of the articles. You can see this in the following code sample, where the property articles is array of IDs.

{
  "_uid": "47d9a0eb-fccd-463a-bfd1-5393afce3ff2",
  "title": "Selected Articles",
  "articles": [
    "7a9efb98-f8e2-4482-b77e-b7d12fd7297c",
    "c3a03db7-b8f8-48ab-abaf-9d84c477a071",
    "b429a8b0-668c-42b3-b043-f4a3de4966c4"
  ],
  "component": "featured-articles",
  "_editable": "<!--#storyblok#{\"name\": \"featured-articles\", \"space\": \"81302\", \"uid\": \"47d9a0eb-fccd-463a-bfd1-5393afce3ff2\", \"id\": \"9879809\"}-->"
  }

You could also include whole content of the articles in the response, but that is another topic covered by this article from Storyblok.

This situation brings up a good question: Where should we request and load our data? Back in the old days, I would do it in the page (in the page folder of Nuxt). The new fetch allows us to do it directly in the component, which then will also render our data. This means, that if we don't use that component, these data will be not requested. That's awesome!

It also means that all of our logic and styling will live in one file. I named this component FeaturedArticles.vue and it looks like this (with a little bit of TailwindCSS styling):

<template>
  <div v-editable="blok">
    <h2 class="pt-2 pl-6 text-lg text-gray-700 italic">{{ blok.title }}</h2>
    <p v-if="$fetchState.error">
      Error occured during the article loading
    </p>
    <p v-else-if="$fetchState.pending">
      Loading articles...
    </p>
    <ul
      v-else
      class="flex py-6 mb-6">
      <li
        v-for="article in articles" :key="article._uid"
        class="flex-auto px-6" style="min-width: 33%">
        <article-teaser
          v-if="article.content"
          :article-content="article.content"/>
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  props: {
    blok: {
      type: Object,
      required: true
    }
  },
  async fetch() {
    this.articles = await this.$storyapi.get(`cdn/stories/`,
        {
          starts_with: 'articles/',
          version: 'draft',
          by_uuids: this.blok.articles
        }
      ).then((res) => {
        return res.data.stories
      }).catch((res) => {
        console.error(res)
      })
  },
  fetchOnServer: true,
  data() {
    return {
      articles: []
    }
  }
}
</script>

You can see in the template that we can end up with three different situations:

  • $fetchState.pending - If the request takes a long time we will inform the user that we are loading articles.
  • $fetchState.error - If we get an error from our end-point, we will let the user know about it. Then we could show a button to renew request.
  • !$fetchState.pending - Finally if the request was succesful, we will render the teasers on the page.

Why do it like this?

  • You can provide better UX to your user.
  • You don't have to use $store.
  • You will load data only when you need them.
  • Your logic lives in one place and is not spread through multiple files.
  • If you decide to remove the component, you will remove all of it's code with it.

You can read more about the new Fetch hook and its option in the official Nuxt.js documentation. This was just the tip of the iceberg. 😏

In the next tip I will compare the difference between the old fetch and the new fetch. Stay tuned and see you soon!

Don't miss out anything about Vue, your favourite framework.

Subscribe to receive all the articles we publish in a concise format, perfect for busy devs.

Related Articles

Advanced i18n in Nuxt using Interpolations

Internationalization it's necessary in a multi-language site. Learn how to do i18n the right way in Nuxt and Vue using the nuxt-i18n module.

Debbie O'Brien

Debbie O'Brien

Aug 17, 2020

Setting up a full static Nuxt site

Overwhelmed by too many options to create a blog? Chill and use Nuxt, Storyblok and TailwindCSS to make it simple, beautiful and incredibly performant

Alex Jover Morales

Alex Jover Morales

Jul 14, 2020

Create Dynamic Titles and Favicons with Nuxt

Thinking on showing a timer on the browser tab? Or different favicons depending on a state? Learn to use vue-meta in your Vue.js apps in this tutorial

Javier Martínez

Javier Martínez

Jun 18, 2020

Sponsors

VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.

Silver
Learning Partner