1

I'm attempting to create a component that gets the current record's Id and queries related records that contain a Geolocation field, so I can populate a map.

While developing this, I created a method that calls an Apex method (passing the recordId), and the component throws the following error when rendering on AppBuilder:

afterRender threw an error in 'c:objectmap' [Cannot destructure property `error` of 'undefined' or 'null'.]

The component's method is this:

@wire(getEnterprise, { recordId: '$recordId'})
retrieveEnterpriseRecord({ error, data}) {
    if (data) {
        console.table(data)
    } else {
        this.error = error
        this.mapMarkers = undefined
        console.error(error)
    }
}

connectedCallback() {
    // this.helloWorld()
    this.retrieveEnterpriseRecord()
}

And the HTML is like this:

<template>
    <template if:true={mapMarkers}>
        <lightning-map
            map-markers={mapMarkers}
            markers-title={markersTitle}
            zoom-level={zoomLevel}
        ></lightning-map>
    </template>
    <template if:true={error}>
        <p>Error: {error}</p>
    </template>
</template>

If I comment out the component's method, and create a "helloWorld" method to populate the error attribute, the component renders without errors, like this:

helloWorld() {
    console.log('hello world!')
    this.error = 'A generic error'
}

What is causing this error? How can I make it stop?

  • Any reasons why you are calling the wired function retrieveEnterpriseRecord() from connectedCallback()? You don't need to explicitly invoke it from any lifecycle hook. As soon as your component is constructed, the wired function will always have values populated in data, error as applicable. – Jayant Das Apr 22 '19 at 1:51
  • I don't fully understand what a function or property being "wired" means. But I want to call different methods depending on what the settings of the component are (what the user sets on the app builder interface). – Renato Oliveira Apr 22 '19 at 13:26
  • As for wired services, you may like to go through the documentation to understand more about it. For settings from app builder -- can you elaborate what are those and how are they set which affects the component? – Jayant Das Apr 22 '19 at 13:44
  • For that, I mean that the component exposes an attribute to the app builder, and then the user chan modify its default value (for example, the zoom level in a map component). That is working as intended. – Renato Oliveira Apr 22 '19 at 13:53
  • So as long as that is working as intended, you don't need to explicitly call the wired function. I have added some details in an answer linking to relevant documentation. Hope that helps you here. – Jayant Das Apr 22 '19 at 14:12
1
  1. You don't need to call retrieveEnterpriseRecord when using wire service.
  2. It will be automatically get called whenever the value in recordId get changes.

  3. If your requirement need to call the method in connectedCallback or constructor then you must use "Call an Apex Method Imperatively" https://developer.salesforce.com/docs/component-library/documentation/lwc/apex

Ex:

import { LightningElement, track } from 'lwc';
import getEnterprise from '@salesforce/apex/YOUR_CLASS_NAME.getEnterprise';

export default class ApexImperativeMethod extends LightningElement {
@track data;

retrieveEnterpriseRecord() {
    getEnterprise({ recordId: '$recordId'})
        .then(result => {
            this.data = result;
        })
        .catch(error => {
            console.log( error );
        });
}

connectedCallback() {
    this.retrieveEnterpriseRecord()
 }
}
| improve this answer | |
1

The error that you are receiving:

Cannot destructure property error of undefined or null

is because of the following as defined in the wired service documentation (emphasis mine):

The property is assigned a default value after component construction and before any other lifecycle event. The default value is an object with data and error properties of undefined

...

The wire service provisions the function an object with error and data properties, just like a wired property.

Now because you are trying to access the wired function before a lifecycle hook function, connectedCallback() in this case and thus you end up with the error you are receiving.


As for the resolution - you don't really need to explicitly invoke the wired function here. The service will render data as soon as the component is constructed. Your reactive property for this wired function is the recordId, so whenever it will change, the component will render the updated data. Refer to this excerpt from the wired service documentation:

We call the wire service reactive in part because it supports reactive variables, which are prefixed with $. If a reactive variable changes, the wire service provisions new data.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.