Something that can catch your attention when debugging an LWC with an @wire, is that if you set a breakpoint just after it, the first time that this breakpoint stops, the data will be undefined. And yes, just the first time, because the code will go through this breakpoint again before you can manually interact with the LWC, and this time, the data will contain information.

My first thought when I first saw this behaviour –  “Hold on, what?!” But I obviously did not understand the wire adapters, but also the LWC lifecycle. Until now!

The Lightning Data Service (LDS) wire adapters are endpoints that can be invoked in a specific way (using @wire) to create a reactive service to read data… But if you want to dig into this, I’ll add some links for you at the end of this post 😉

Now that we have defined what a wire adapter is, let’s have a look at how it fits in the LWC lifecycle. I will explain this with an easy code example.

import { LightningElement, wire, api } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/MyCustomObject__c.Name';

export default class DoTheThing extends LightningElement {
    recordId = 'a073i0000049kNMAAY';

    @wire(getRecord, {recordId:'$recordId', fields: [NAME_FIELD]})
    myWiredRecord ({data, error}){
        debugger;
        if(data){
            debugger;
            //codigo
        }
    }
}

I want you to pay attention at the lines with the debugger, so lines 10 and 12. Because the browser will not always will stop in both, but will stop depending on what the data contains.

In what apparently is the “first” run, the browser will stop only in line 10 debugger. This is because the data contain undefined at this point, and so, the if statement will evaluate to false forcing the browser do not follow this path. It will be at the “second” run when the data will contain a value different to undefined.

Alright, we can observe a few things here:

  1. The first thing executed here is the constructor. At this point, properties are set, for example the recordId.
  2. Just after the constructor, and before any other LWC lifecycle event, the wire service sends a default object like the following {data: undefined, error: undefined}.
    This default object is responsible at making the browser stop at line 10 debugger and showing undefined as the value for data.
  3. connectedCallback is executed, and after it, the @wire is called again. This time @wire consumes the values stored in recordId and [NAME_FIELD]. And so, data or error values will be modified and in case everything worked accordingly the line 12 debugger will force the browser to stop.

So, Our example lifecycle will be something like this:

  1. constructor
  2. Properties are set
  3. wire service sends a default object {data: undefined, error: undefined}
  4. Line 10 debugger
  5. connectedCallback
  6. wire service returns a new record, but this time the wire service is using the info stored in recordId and [NAME_FIELD] and bringing that value from the cache or server
  7. Line 10 debugger
  8. wire service returns data
  9. Line 12 debugger

I will finish by adding that there are other events that can make the @wire react, besides the modification of the parameters. These are the record modification in the LDS cache or by forcing the wired property to be refreshed.

And if you want to learn more about wire adapters, the LDS and the LWC lifecycle, I recommend you to have a look at the following links.

 

Photo by Steve Johnson on Unsplash

Pedro Molina May 12, 2021

Leave a Reply

Your email address will not be published. Required fields are marked *