A - Z Guide to Using the Wire Decorator in LWC Salesforce
// 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) {} }
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:
- body (Object or Array) - The body of the response, which is defined by the underlying API.
- 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.
- 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.
- statusText (String) - Contains the status message corresponding to the status code, for example, NOT_FOUND for a status code of 404.
- array of objects - return from UI API read operations like getRecord wire adapter
- an object - return from all the other API's like createRecord, Apex response, Network failure etc.
<!-- 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
Post a Comment