Skip to content

lwc 301 lds advanced

James Hou edited this page May 13, 2021 · 2 revisions

A couple of concepts for more advanced usage of LDS Adapters:

  • Wire infrastructure
  • Multi wire flow control
  • Network boxcar-ing

Wire infrastructure

Wires are promises under the hood. During the lifecycle of an LWC, wires are called between constructor and connectedCallback (AFAIK, this is undocumented - I sourced this from some folks at SFDC).

However, the design of a wire call is very interesting. It will always call server twice:

  1. First is usually undefined since it's variable you've bound with the magic syntax $myVar will likely be unavailable between constructor and connectedCallback.
  2. Second call is when the wire framework detects a change in the magic syntax bound prop.

Concrete example: When using the getRecord adapter which accepts the recordId variable, it will call one time with undefined and the second time when the @api recordId interface passes the actual recordId from the flexipage container, through the api of the LWC, into the bound property.

This "re-assignment" of the bound variable is what triggers a wire call and triggers its reactivity and cacheable=true infrastructure.

Multi wire flow control

Note: Forward Looking Statement, there is some variant of promise.all() in the works for wires. Or, some other variant which should grant a little more predictability here. until then, this is the workaround.

Once you understand how (intentional) variable assignment triggers the actual desired wire call, you can then manipulate this to your advantage.

Here is an example:

  // Goes first
  @wire(getObjectInfo, { objectApiName: '$_objectApiName' })
  currentObjectWire({ error, data }) {
    ...
    this._getRecordFields = ['MyField__c']
    ...
  }
  // Goes second, since not all bound variables are truthy on load - the callback of the first will get this to fully resolve.
  @wire(getRecord, { recordId: '$recordId', fields: '$_getRecordFields' })
  currentRecordWire({ error, data }) {
    ...
  }

Network boxcar-ing

This originates from the aura infrastructure and has (I believe) carried over in some way in LWC-land. However, this isn't documented clearly so this is mostly speculative.

For prior art in Aura, please see here:

For LWC consider the following sources:

const promises = recordInputs.map((recordInput) => updateRecord(recordInput));
Promise.all(promises)
  .then((contacts) => {
    ...
  })
  .catch((error) => {
    ...
  });

or using async await

await Promise.all(
  recordInputs.map(async recordInput => {
    try {
      const successResult = await updateRecord(recordInput);
      ...
    } catch (error) {
      ...
    }
  })
);

Anecdotally, I've found that LDS adapters that allow for DML (updateRecord, deleteRecord) are boxcar-ed by the framework so it's not 1 network request per record.