web123456

【vue3 Project】Solved “TypeError: Cannot read properties of undefined (reading ‘xxx’)”

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$apiSend 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.$apiIt 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