I'm hitting this route: http://site.dev/person/1
And my component looks something like this:
// PeopleComponent.vue
<template>
<div>
<template v-if="person == null">
<b>Error, person does not exist.</b>
</template>
<template v-else>
<pre> {{ person }} </pre>
</template>
</div>
</template>
<script>
export default {
mounted() {
this.$store.dispatch('getPeople');
}
computed: {
// represents the person whose id potentially matches the value of `/:id` in route.
person(){
let id = parseInt(this.$route.params.id)
let person = null
if(id > 0)
person = this.$store.state.people.find(p => p.id == id)
return person;
}
}
}
</script>
// [styles]
What I'm doing in this component:
I get an ID in my URL. The ID represents a specific resource being shown on this page. I have a
person()computed property to retrieve the object whose ID matches the parameter in the URL from my Vuex store.
The desired outcome:
At the top of the page, I would like to display an error message if the object cannot be found (if say, for example, someone types an ID that doesn't exist in the array of objects in the store). If the item is found, a simple dump of the object is fine. This currently works, but the delay between fetching the data from the API and finding the right object in the store seems to be just long enough to briefly show the error message as if the object could not be found when the page first loads. When tested with a slower network speed, this error message is visible for several seconds. I want to eliminate it such that it does not appear at all if the object exists.
What I've tried:
v-cloak- tried applying this to every parent div, even thediv#appitself, to no avail. I must be doing something wrong.v-if- as seen above in the example
Some pointers would be appreciated, thank you!
Update 31/03/2020
As per Phil's suggestion, I tried to incorporate a flag to indicate when the page is ready. I did it in two different ways.
Method #1
Made the mounted() 'async' and added an await on the action that retrieves people from my API. Setting flag to true after it:
async mounted() {
await this.$store.dispatch('getPeople');
this.loaded = true;
}
But I still see the error message, briefly.
Method #2
Use a then callback on the action, and set the flag to true inside the callback
mounted() {
let vm = this
vm.$store.dispatch('getPeople').then(() => {
vm.loaded = true;
})
}
Both methods don't stop the message from appearing.
I suspect that this is what's happening:
Core rule
Error should ONLY show if
loaded=trueandperson=null
- Page loads,
loadedisfalseandpersonisnull. Error won't show. - Page does a call to get people from API. Error still isn't showing.
- After the call,
loadedhas been set totrue[At this point,loadedistrueandpersonhasn't been resolved by the computed property yet, THIS is where I believe I'm seeing the error.] - Computed property finds the relevant record from the store on the next tick.
Personis no longernull, so the error disappears.
Edit 01/04/2020
Answering Phil's question: What does your getPeople() action look like?
getPeople({ commit }) {
axios.get('/get/people')
.then(response => {
commit("getPeople", response.data);
})
.catch(error => {
console.log(error);
})
},