Nuxt Fetch Show Loading

June 12, 2020

Option 1: $fetchState.pending

Show loading at page component

<template>
  <div>
    <div v-if="$fetchState.pending">Loading ...</div>
    <div v-else-if="$fetchState.error">Error: {{ $fetchState.error.message }}</div>
    <div>
      {{ title }}
    </div>
  </div>
</template>

<script>
export default {
  async fetch() {
    // const HOST = 'http://localhost:8080' // required for server-side fetch
    // const url = new URL(`/data/test.json`, HOST)
    const url = 'https://jsonplaceholder.typicode.com/posts/1'
    // alternatvely, you could use $axios or $http
    const res = await fetch(url)
    const data = await res.json()

    this.title = data.title

    // sleep 5s
    // await new Promise(r => setTimeout(r, 5000))
  },
  data() {
    return {
      title: null
    }
  },
}
</script>

Option 2: $nuxt.$loading

Via nuxt loading property.

<template>
  <div>
    <div v-if="!$fetchState.pending && !$fetchState.error">
      {{ title }}
    </div>
  </div>
</template>

<script>
export default {
  loading: false, // disable default loading handling
  async fetch() {
    // show loading
    this.$nuxt.$loading.start()

    // const HOST = 'http://localhost:8080' // required for server-side fetch
    // const url = new URL(`/data/test.json`, HOST)
    const url = 'https://jsonplaceholder.typicode.com/posts/1'
    // alternatvely, you could use $axios or $http
    const res = await fetch(url)
    const data = await res.json()

    this.title = data.title

    // sleep 5s
    // await new Promise(r => setTimeout(r, 5000))

    // hide loading 
    this.$nuxt.$loading.finish()
  },
  data() {
    return {
      title: null
    }
  },
}
</script>

Edit nuxt.config.js to configure loading bar color and size.

export default {
  loading: {
    color: 'blue',
    height: '5px'
  }
}

Option 3: Show Loading via Layout

Use master layout file to show loading.

Edit store/index.js.

export const state = () => ({
  loading: false
})

export const mutations = {
  loading(state, value) {
    state.loading = value
  }
}

export const actions = {

}

Page component

<template>
  <div>
    <div v-if="!$fetchState.pending && !$fetchState.error">
      {{ title }}
    </div>
  </div>
</template>

<script>
export default {
  loading: false, // disable default loading handling
  async fetch() {
    // show loading
    this.$store.commit('loading', true)

    // const HOST = 'http://localhost:8080' // required for server-side fetch
    // const url = new URL(`/data/test.json`, HOST)
    const url = 'https://jsonplaceholder.typicode.com/posts/1'
    // alternatvely, you could use $axios or $http
    const res = await fetch(url)
    const data = await res.json()

    this.title = data.title

    // sleep 5s
    // await new Promise(r => setTimeout(r, 5000))

    // hide loading 
    this.$store.commit('loading', false)
  },
  data() {
    return {
      title: null
    }
  },
}
</script>

Edit layouts/default.vue

<template>
  <div>
    <div v-if="loading">Loading ...</div>
    <nuxt/>
  </div>
</template>

<script>
export default {
  computed: {
    loading() {
      return this.$store.state.loading
    }
  }
}
</script>
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.