3

I created component as Lightning Web Component. In VSCode it's ok. When in Lightning App Builder I added this component, there is a bug: "Error during LWC component connect phase: [Cannot read property 'fields' of undefined]"

product.html:

<template>
  <div class="container">
      <a onclick={productClick}>
        <div class="product">{name}</div>
      </a>
      <a onclick={addToCart}>
        <div class="product">Add to cart</div>
      </a>
  </div>
</template>

product.js:

import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const FIELDS = [
  'Account.Name',
  'Account.Phone'
];

export default class Product extends LightningElement {
  @api item; // public property
  item = recordId;

  @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
  account;

  get name() {
    console.log('Returned value: ' + this.account.data.fields.Name.value);
    return this.account.data.fields.Name.value;
  }

  productClick() {

  }

  addToCart() {
    
  }
}

I use API v.51. It is programmed according to this manual.

Elo
  • 226
  • 5
  • 19

3 Answers3

2

The HTML tries to load first (to as soon as possible show something, anything to the user. maybe some placeholder, maybe loading icon...). This is almost pure html, your @wire didn't return data yet so your this.contact is undefined. And yet the HTML calls the getters so null.fields results in error.

Try wrapping the HTML in <template if:true> or in all getters write something like return this.account && this.account.data ? this.account.data.fields.Name.value : null;

See last answer in https://developer.salesforce.com/forums/?id=9062I000000QwLGQA0 or this is decent too (but it's for bit different usage of @wire): https://salesforce.stackexchange.com/questions/264669/how-to-avoid-error-cannot-read-property-of-undefined-using-two-lwc-wired-propert

eyescream
  • 18,088
  • 2
  • 34
  • 46
  • Object [Account is filled](https://pasteboard.co/JSJnH9O.png). And also custom object cannot be read. Is it needed any rights for read? Possibly, where can I check access rights? – Elo Mar 15 '21 at 13:32
  • Hey @Elo, this answer is correct, you have to check the account data first before accessing the property of it. The wire runs asynchronously and hence there might be some time span in which the this.account would not be having any data... So in that time if rendering happens as its also asynchronous,the getter method invokes which will access the this.account ( if null) will give you the error. – Jasneet Dua Mar 21 '21 at 07:26
0

This is the edited code: product.html:

<template>
  <p>LWComponent</p>
  <template if:true={account}>
    <div class="container">
        <a onclick={productClick}>
          <div class="product">{name}</div>
          <!--<img class="product-img" src={product.fields.Picture_URL__c.value}></img>-->
        </a>
        <a onclick={addToCart}>
          <div class="product">Add to cart</div>
        </a>
    </div>
  </template>
</template>

product.js:

import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const FIELDS = [
  'Account.Name',
  'Account.Phone'
];

export default class Product extends LightningElement {
  @api recordId;

  @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
  account;

  get name() {
    console.log("Yes, I'm here :)");
    if (this.account) {
      console.log('this.account: ' + JSON.stringify(this.account));
    } else {
      console.log("'this.account' does not exist.");
    }
    if (this.account.data) {
      console.log('this.account.data: ' + JSON.stringify(this.account.data));
    } else {
      console.log("'this.account.data' does not exist");
    }
    if (this.account.fields) {
      console.log('this.account.fields: ' + JSON.stringify(this.account.fields));
    } else {
      console.log("'this.account.fields' does not exist");
    }
    return this.account && this.account.data ? this.account.data.fields.Name.value : null;
    //return this.account.data.fields.Name.value;
  }
}

Console listing:

Yes, I'm here :)
this.account: {}
'this.account.data' does not exist
'this.account.fields' does not exist

In account is nothing, I don't understand why.

Elo
  • 226
  • 5
  • 19
  • Your `@wire` listens to dynamic changes to `$recordId`, it's the input parameter to it. But you don't have an `@api recordId;` variable defined so there's nothing to listen to, nothing to pull data based on. "recordId" and "objectApiName" are 2 special variables, https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_record_context. – eyescream Mar 15 '21 at 13:47
  • It was needed to add in variable recordId Id from database: `@api recordId = 'a010900000giYo0AAE';` This is how it works. – Elo Mar 17 '21 at 09:39
0

I added '@api recordId;' And file product.js-meta.xml file I edited:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>51.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
    <target>lightning__RecordPage</target>
    <target>lightning__HomePage</target>
    <target>lightningCommunity__Default</target>
  </targets>
  <targetConfigs>
    <targetConfig targets="lightningCommunity__Default">
      <property
        name="recordId"
        type="String"
        label="Record Id"
        description="Automatically bind the page's record id to the component variable"
        default="{!recordId}" />
    </targetConfig>
  </targetConfigs>
</LightningComponentBundle>

Result is the same. In object Account is nothing.

Elo
  • 226
  • 5
  • 19