Resolve "TypeError: Cannot read properties of undefined (reading 'xxx')"
I have searched this question online for a long time, and the reasons for the bugs summarized online are as follows:
//This error My problem is that the data to be used cannot read this property (I used vue)
//1. Check whether the attribute defined by your data does not have the attribute you use. If not, define one, as follows:
#template
<div class="he-info__item">
<span class="he-label">Name of the consignee:</span>
<span class="he-value">{{ detail.buyer.name }}</span>
</div>
<div class="he-info__item">
<span class="he-label">Contact information:</span>
<span class="he-value">{{ detail.buyer.mobile }}</span>
</div>
#js
export default {
data () {
detail: {
buyer: {
name: "",
mobile: "",
},
user: {
nickname: "",
},
},
}
}
//2. It may also be that the data returned to you by the backend does not have this attribute, or some returned data and some are null.
// You can't write at this time {{ || "" }} Otherwise, an error will be reported. Cannot read properties of undefined (reading 'xxx')" can be solved as follows:
#template
<div v-if="!!">{{ item.invite.nickname }}</div> //It will only be displayed if this property is present
// Or that's OK
<div v-if="item?.invite">{{ item.invite.nickname }}</div> //It will only be displayed if this property is present
<div v-else>{{ "" }}</div> //No return or null directly fill in ""
//3. Another type of online is that the view has not been updated and the data has not been returned yet. You can start using this property. You can add this.$nectTick (()=>{//get data}) to wrap it, but I have never tried it.
But none of the above methods can solve my bug.
My related code snippet:
Define a getUserList function and mount it in the onMounted function. When loading the page, I first pass the globally mounted$api
Send a request to the backend to obtain list data
import { onMounted, reactive, ref, getCurrentInstance } from 'vue'
// Below is the code in the setup
const { ctx } = getCurrentInstance()//This is to get this pointer in vue3, because there is no this in vue3
onMounted(() => {
getUserList()
})
const getUserList = async () => {
let params = { ...user, ...pager }
const { list, page } = await ctx.$api.getUserList(params)
userList.value = list
pager.total = page.total
}
There is no logical problem, and the above three situations have not occurred.
My solution:
First of all, the meaning of this error is roughly: the undefined attribute cannot be found.
What this means in my code is: Can't find ctx.$api
, that isctx.$api
It is undefined.
Then I printed some values in the console:
console.log('ctx: ', ctx)
console.log('ctx.$api: ', ctx.$api) //undefined
It turns out that ctx.$api is undefined, and ctx does not have the $api we bound to
So, I guess that $api global binding is not effective
To verify, I bound something to the global object and tested it:
// In
app.config.globalProperties.$user = {
name: 'Mei Changsu',
weapons: 'Long Sword',
title: 'assassin'
}
//Use in your own page:
console.log(ctx.$user)// undefined
console.log(ctx.$user.name) //TypeError: Cannot read properties of undefined (reading 'name')
So the reason for the bug is that the global binding of vue3 is not effective
So, I've bound it to that page:
import { onMounted, reactive, ref, getCurrentInstance } from 'vue'
import api from './../api'
setup(){
onMounted(() => {
getUserList()
})
const getUserList = async () => {
// ('ctx: ', ctx)
// ('ctx.$api: ', ctx.$api)
ctx.$api = api //Perform local binding and take effect! ! !
let params = { ...user, ...pager }
const { list, page } = await ctx.$api.getUserList(params)
console.log('ctx.$api successfully bound')
userList.value = list
pager.total = page.total
}
}
At this time the page data has been returned