Reputation: 13
I am new to vue-router navigation guards and so I recently realized that I needed to use beforeRouteUpdate
guard for reused components where for example: Going from /foo/1
to /foo/2
However, while coming to /foo/1
, I pulled data from database through an axios call and before going to /foo/2
, I need to pull new data again through the axios call.
This is where I face a problem where the navigation guard beforeRouteUpdate
loads the component /foo/2
before my data loads from the axios call and thus I get null in a few of my variables.
How can I make beforeRouteUpdate
wait to load the next component so that all my data is loaded from the axios calls?
As for my code, it looks like this:
beforeRouteUpdate (to, from, next) {
Vue.set(this.$store.state.user, 'get_user', null)
this.$store.dispatch(OTHER_PROFILE_GET, to.params.id).then(resp => {
console.log(resp);
if(this.$store.getters.is_user_loaded) {
next()
} else {
this.$store.watch((state, getters) => getters.is_user_loaded, () =>
{
if(this.$store.getters.is_user_loaded) {
console.log(this.$store.state.user.get_user);
console.log('comes here');
next()
}
})
}
})
},
To explain my code further, I have called this method in my component and so I when I go from /user/1
to /user/2
I dispatch a Vuex action which makes an axios call to get the new profile details but before the axios call completes and loads the data in the Vuex state, the beforeRouteUpdate
already loads the next component.
Upvotes: 0
Views: 3503
Reputation: 164980
First, your action should perform any state mutation such as setting user.get_user
to null
. I'm also not sure why you've added a watch; your action should only resolve when complete. For example
actions: {
[OTHER_PROFILE_GET] ({ commit }, id) {
commit('clearUserGetUser') // sets state.user.get_user to null or something
return axios.get(`/some/other/profile/${encodeURIComponent(id)}`).then(res => {
commit('setSomeStateData', res.data) // mutate whatever needs to be set
})
}
}
then your route guard should have something like
beforeRouteUpdate (to, from, next) {
this.$store.dispatch(OTHER_PROFILE_GET, to.params.id).then(next)
}
In order to prevent errors from trying to render null
data, use your getters. For example, say your getter is
getters: {
is_user_loaded (state) {
return !!state.user.get_user
}
}
in your component, you can map this to a computed property...
computed: {
isUserLoaded () {
return this.$store.getters.is_user_loaded // or use the mapGetters helper
},
user () {
return this.$store.state.user.get_user // or use the mapState helper
}
}
then in your template, use this logic to conditionally render some data
<div v-if="isUserLoaded">
Hello {{user}}
</div>
<div v-else>
Loading...
</div>
This is the suggested approach in the vue-router guide for beforeRouteUpdate
Upvotes: 3