0👍
This is happening because <p>
is being rendered while product is still an empty object (product: {}
).
You could use v-if
to render only if product already has been loaded.
<template>
<p v-if="dataLoaded">Sold By: {{ product.user.name }}</p>
</template>
<script>
export default {
data() {
return {
product: {},
dataLoaded: false,
};
},
methods: {
loadData() {
axios.get("/api/" + this.$route.params.slug + "/product").then(
(response) => {
this.product = response.data;
this.dataLoaded = true;
},
() => {}
);
},
},
created() {
this.$Progress.start();
this.loadData();
this.$Progress.finish();
},
};
</script>
1👍
The error is self-explanatory: you’re using {{product.user.name}}
in the template. But before the product
has returned from BE, product.user
is undefined
and therefore does not have a .name
property.
The simplest fix would be to place a v-if
on the <p>
:
<p v-if="product.user">Sold By: {{product.user.name}}</p>
Another generic solution for this type of problem is to use a computed:
<template>
<p>Sold By: {{productUserName}}</p>
</template>
<script>
export default {
// ...
computed: {
productUserName() {
return this.product.user?.name || '';
}
}
// ...
}
</script>
You can read more about optional chaining operator (used above) (?.
) here.
Because it’s a fairly new addition to JavaScript, Vue doesn’t currently support it in <template>
tags (but it works in <script>
).
Additional note: a common mistake is to add an additional data
member instead of using the source of the error (product.user
in this case) either directly or through a computed
. This creates two problems:
- it decouples
product.user
from rendering the<p>
. Which means that if BE returns aproduct
without auser
, you’ll still get the error, because you’ve setdataLoaded
totrue
but the template still tries to read the property.name
ofuser
, which is falsy and therefore does not have a.name
. - you create unnecessary boilerplate: anyone trying to understand or modify your code at a later time has to figure out the arbitrary connection between
dataLoaded
andproduct.user
.
One of the reasons Vue is loved for is because it doesn’t require boilerplate code, unlike other frameworks (i.e: Angular). Keep it that way! By using v-if="product.user"
in the template, someone reading that code will immediately understand the rendering logic, without having to look at the component code. Decreasing the time needed to figure out the code on a regular basis will greatly decrease the time needed to modify it, should you (or someone else) ever need to. This results into more flexible, more scalable code. Less bugs, less time spent => more money.