I'm using Nuxt with Vue Router and Axios. I see Vue Router has this fantastic feature called Navigation Guards.
Unfortunately, in the example below, my beforeRouteEnter()
function is called but seems to exit and switch pages before my manual next()
method is called in fetchPageData(next)
.
What is the correct pattern here?
export default {
beforeRouteEnter (to, from, next) {
next(vm => {
vm.fetchPageData(next);
});
},
methods: {
async fetchPageData(next) {
const result = await this.$axios.$get('/api/v2/inventory/3906?apiKey=f54761e0-673e-4baf-86c1-0b85a6c8c118');
this.$store.commit('property/setProperty', result[0]);
next();
}
}
}
I assume that my first call to next(vm => {})
is running asynchronously, allowing execution to continue, resulting in a page change before I (most likely incorrectly) try to callback next().
Vue Fetch data from API example To get the actual JSON body of the response, we use response. json() method. We can also access metadata such as headers , status , statusText , type , url from the Response object. The response Promise does not reject on HTTP errors (for example: 404 , 500 ).
Using Props To Share Data From Parent To Child # VueJS props are the simplest way to share data between components. Props are custom attributes that we can give to a component. Then, in our template, we can give those attributes values and — BAM — we're passing data from a parent to a child component!
To do this, you need to add the router-view component inside your App. vue file. This component tells Vue Router to mount any component associated with a route where <router-view /> is. Save and exit the main.
You are right, calling next()
second time is incorrect. Your first call to next()
tells Router "go on, you can proceed with changing active component (create/mount/render) and when the component is created, call my callback (passed as an argument to next()
)
You can follow guidance in Data fetching - fetching before navigation Docs ie. fetching data first and call next()
after but that requires to extract fetch logic from the component itself.
Generally I find easier to write all component in the way assuming data are not here on 1st render and are coming later when all async calls resolve...
UPDATE Nuxt async data fetching options
As you are using Nuxt.js you have some other options how to use async data:
asyncData
method except it doesn't set the component data and allows you to put the data into the store. Returning Promise from fetch
method will make Nuxt wait for promise to resolve before it renders the component...data
. Returning Promise from asyncData
method will make Nuxt wait for promise to resolve before it renders the component...export default {
async fetch({store, $axios}) {
const result = await $axios.$get('/api/v2/inventory/3906');
store.commit('property/setProperty', result[0]);
}
}
What is happening there, is that you already calling
next
and that's why the route enters immediately.
Where you are calling next ?
beforeRouteEnter (to, from, next) {
next(vm => { // <= HERE you execute next
vm.fetchPageData(next);
});
},
And the above code will execute vm.fetchPageData
when the component is already rendered.
So even if you don't call next
on the fetchPageData
the route will enter.
By assuming that you want to enter the view after certain data is fetched by BE you can use beforeEnter
on the router config:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
axios.get('api/...')
.then(response => {
store.commit('mutation', response)
next()
})
.catch(e => {
alert('Something went wrong')
next(false)
})
}
}
]
})
Another solution would be to allow the route to enter but show a loader while data is being fetched: Checkout this answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With