A - Z Guide to Using the Wire Decorator in LWC Salesforce


Certainly! In Salesforce Lightning Web Components, the "wire service" is a feature that brings data to your component. Imagine this data as a never-ending river of information, and each piece of information in this river is like an updated version of the one before it. What's special is that once you receive a piece of data, it's like taking a snapshot in time; you can't change it. Instead, as new data becomes available, it replaces the previous one in the stream. This way, your component always has the latest and most up-to-date information without you having to constantly ask for updates. It's like having a continuous flow of fresh data at your fingertips.

Syntax

// Wire to a property @wire (methodName, {parameterName: '$value'}) result;

// Wire to a function @wire (methodName, {parameterName : value}) callbackFtn(result) {

const {data, error} = result; if(data) { // Add logic }   else if(error) {} }
When you should use wire to function
when processing or performing logic on the return value is necessary whenever new data is provisioned. The callback function receives the result when the response is returned from apex or method. The response or result is an object having data and error properties.

Wire is good for read operation
The Lightning Web Components engine receives control flow delegation from the wire service. For read actions, delegation of control works well; however, it is not as effective for create, update, and delete operations. You desire total control over actions that alter data as a developer. For this reason, a JavaScript API is used for create, update, and delete actions rather than a wire service.

Example of usage of wire:

<!-- wireGetValue.html --> <template> <lightning-card title="My Account Record" icon-name="standard:account"> <template lwc:if={account.data}> <div class="slds-m-around_medium"> <p>{name}</p> </div> </template> <template lwc:if={account.error}> <c-error-panel errors={account.error}></c-error-panel> </template> </lightning-card> </template>

// wireGetValue.js import { LightningElement, api, wire } from "lwc"; import { getRecord } from "lightning/uiRecordApi"; import REVENUE_FIELD from "@salesforce/schema/Account.AnnualRevenue"; const fields = [REVENUE_FIELD]; export default class WireGetValue extends LightningElement { @api recordId; @wire(getRecord, { recordId: "$recordId", fields }) account; // private }

As shown in above code, If the property (account) decorated with @wire is used as an attribute in the template and its value changes, the wire service provisions the data and triggers the component to rerender. The property is private, but reactive.

The $ prefix tells the wire service to treat it as a property of the class and evaluate it as this.propertyName. The property is reactive. If the property’s value changes, new data is provisioned and the component rerenders.

With @Wire we can use reference to field or object as well as string representation of field or object.

Read Leveraging Object and Field References in LWC Wire Adapters to learn more about how reference field imports work, such as the one we used in the code above.
import REVENUE_FIELD from "@salesforce/schema/Account.AnnualRevenue"; 

The default value of the property is an object with data and error properties of undefined.

{ data: undefined, error: undefined }

When data becomes available from the wire adapter, it’s set in the data property (error remains undefined). When newer versions of the data are available, data is updated.

If an error occurs in the adapter, for example when retrieving the data, error is populated with an error object (data is set to undefined).

@wire uses cache memory, which makes it efficient 
To use @wire to call an Apex method, you must set cacheable=true. 

Marking a method as cacheable improves your component’s performance by quickly showing cached data from client-side storage without waiting for a server trip. If the cached data is stale, the framework retrieves the latest data from the server.

If a component knows that a cached value is invalid, for example when underlying data changes, it can query the server for updated data and refresh the cache with refreshApex() from @salesforce/apex.

The function provisions the data using the configuration bound to the @wire and updates the cache. Invoke refreshApex() only when necessary because it incurs a network trip to query the server.

import { LightningElement, wire } from 'lwc'; import getAccountList from '@salesforce/apex/WireExampleController.getAccountList'; import { refreshApex } from '@salesforce/apex'; export default class WireExample extends LightningElement { accounts; error; /** Wired Apex result so it can be refreshed programmatically */ wiredAccountsResult; @wire(getAccountList) wiredAccounts(result) {         // Hold on to the provisioned value so we can refresh it later. this.wiredAccountsResult = result; if (result.data) { this.accounts = result.data; this.error = undefined; } else if (result.error) { this.error = result.error; this.accounts = undefined; } }     async deleteAccount(event) {         // await deletingAccount....         await refreshApex(this.wiredAccountsResult); // do something with the refreshed data in this.wiredAccountsResult     }    

}

Use one @wire output as another @wire input
For example, you could use $record.data.fieldName as an input to another wire adapter.

import { LightningElement, api, wire } from "lwc"; import getData from'@salesforce/apex/MyApexClass.getData'; import getAnotherData from'@salesforce/apex/MyApexClass.getAnotherData'; export default class WireGetValue extends LightningElement { @api recordId; @wire(getData, { recordId: "$recordId" }) account; // private @wire(getAnotherData, {status: "$account.data.status__c"}) response; // private

}

Understand the error structure thrown by wire

The error object has the following in it:

  1. body (Object or Array) - The body of the response, which is defined by the underlying API.
  2. ok (Boolean) - Specifies whether the response was successful or not. For an error, ok is always false and contains a status in the range 400–599.
  3. status (Number) - Contains the status code of the response, for example, 404 if a resource is not found or 500 for an internal server error.
  4. statusText (String) - Contains the status message corresponding to the status code, for example, NOT_FOUND for a status code of 404.
The type of data contained in the error.body payload varies depending on the API that returns it.
  1. array of objects - return from UI API read operations like getRecord wire adapter
  2. an object - return from all the other API's like createRecord, Apex response, Network failure etc. 
Best way to handle the error.body  

<!-- handleError.html --> <template> <lightning-card title="Handle Error" icon-name="standard:contact"> <template lwc:if={error}> <p>{error}</p> </template> </lightning-card> </template>

// handleError.js import { LightningElement, api, wire, track } from "lwc"; import { getRecord } from "lightning/uiRecordApi"; const fields = [ // This invalid field causes @wire(getRecord) to return an error "Contact.invalidField", ]; export default class handleError extends LightningElement { @api recordId; @track error; @wire(getRecord, { recordId: "$recordId", fields }) wiredRecord({ error, data }) { if (error) { this.error = "Unknown error"; if (Array.isArray(error.body)) { this.error = error.body.map((e) => e.message).join(", "); } else if (typeof error.body.message === "string") { this.error = error.body.message; } this.record = undefined; } else if (data) { // Process record data } } }

Comments

Popular posts from this blog

How to Add a Dynamic Child List to Parent in Apex Class || Trigger using map

(Salesforce Apex 2024 Release) getSalesforceBaseUrl method is deprecated