[Vuejs]-How to properly use the new fetch() hook in Nuxt 2.12 for SSR?

2👍

RESOLVED: Nuxt prompted me with a tiny warning saying that “node-fetch” at least at version 2.6.0 is required. For some reason mine was at 2.1.2.

👤sintj

7👍

As far as SSR is concerned, fetch is used the same way asyncData is used (although there is a difference in page transition timing).

The difference between fetch and asyncData:

  • asyncData does not have access to this, while fetch (in Nuxt >= 2.12) does.
  • asyncData‘s return value sets the data of the component, while fetch‘s return value does not because fetch already has access to this, so it could set data props directly.
  • fetch is controlled by two options (fetchOnServer and fetchDelay), while asyncData has no options. When fetchOnServer (true by default) is set to false, the fetch hook is only called client-side.
  • fetch is coupled with the $fetchState object, which provides pending and timestamp (related to the current state of the fetch operation); and the error function (allows you to display an error message). Note that asyncData is also provided the error function in its context argument.
  • fetch allows for faster page transitions (according to RFC 27).
  • asyncData is only available to pages, while fetch can be used by any component (including pages).

Aside from the differences above, the semantics of the two methods are identical.

It seems fetch is unofficially the successor of asyncData even though both exist simultaneously without a deprecation notice. Since fetch provides more functionality and addresses the problems of asyncData, I would reccomend using fetch exclusively.

👤tony19

2👍

If you are looking for a way to have a loading state for your page components you could use the data with asyncData,

        data(){
            return{
                loading: true
            }
        },

        async asyncData(context) {
            try{
                const res = await context.app.$prismic.api.query(context.app.$prismic.predicates.at('my.category.uid', context.app.$route.params.sub))
                const el = res.results[0]
                const query = await context.app.$prismic.api.query([context.app.$prismic.predicates.at('document.type','sub-category'), context.app.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
                const docs = query.results
                const loading = false
                return {docs, el, loading}
            }   
            catch (e) {
                console.log(e)
            }
        }

if you use prismic, (and if you didn’t register it as a plugin) you could inject prismic into the context through a plugin

import prismic from 'prismic-javascript'

export default (inject) => {

    inject('prismic', prismic)
}

So now you have access to $prismic in the context.

Another approach that I am using when dealing with loading states is using a store module for handling the state of the request.

plugins/loading.js

export default ({store},inject) => {
    inject('changeLoading', function(){
            store.dispatch('changeLoading')
        }
    )
}

store/index.js

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

export const mutations = {
    CHANGE_LOADING(state){
        state.loading = !state.loading
    }
}

export const actions = {
    changeLoading({commit}){
        commit('CHANGE_LOADING')
    }
}

export const getters = {
    getLoading(state){
        return state.loading
    }
}

so now instead of having a local loading state inside your components you would have a centralized state inside your store that you can change and get.

        data(){
            return{
                loading: this.$store.getters['getLoading']
            }
        },

        async asyncData(context) {
            try{
                context.app.$changeLoading()
                const prismicData = await context.app.$prismic(...)
                context.app.$changeLoading()
                return {prismicData}
            }   
            catch (e) {
                context.app.$changeLoading()
                console.log(e)
            }
        }
👤Eduard

Leave a comment