Lightning Web Component Best Practices

AMIT SINGH
7 min readOct 19, 2022

--

Lightning Web Component is a very demanding technology these days for any Salesforce Developer. As a Salesforce developer, you might be developing the lightning web component on the daily basis.

So, in this blog post, we will talk about what are the things that you need to keep in mind while developing the LWC.

Name It the Right Way

Using the correct name of the Lightning Web Component bundle is very important as if you miss the right naming convention then you might get into a problem while using composition. Here are a few best practices that you should keep in mind –

  1. Always use lowerCamleCase for the component name. Use helloWorld instead of HelloWorld
  2. LWC uses a kebab case for composition. For Example, if the Component name is myFirstLWC then you need to use my-first-l-w-c inside the parent component

Modular Development

Developing the Lightning web component becomes easy when you have got basic knowledge about it. However, we should always think can I make this component reusable so that other developers can use it when they are in need?

Example — You have been asked to develop a component to display the account record in the form of Tile along with some additional information about Opportunity & Cases.

In the above example, instead of writing the putting everything within the same lightning component, we should break down those into 3 different components like below

  1. Account Tile Component to display the account information
  2. Case Information Component to display the information related to cases.
  3. Opportunity Information Component to display opportunity information

Use @Cacheable=True

When you have the requirement to display the records in the Lightning Web component then we should always store the cache on the browser side.

We can achieve this with the help of @wire decoration and @cacheable=true on the Apex Method side.

public with sharing class Constants {
public Constants() {
}
@AuraEnabled(cacheable=true)
public static List<Contact> getAllContacts(){
try {
return [SELECT Id, Name, Email, Phone FROM Contact WHERE Email <> null LIMIT 200];
} catch (Exception e) {
throw new AuraHandledException(e.getMessage());
}
}
}

Use Lightning Base Components

Always try to use Lightning Base Components wherever it is possible instead of developing a custom solution for the same requirement.

For Example, If you want to display the icon or avatar then use lightning base tags instead of developing it using CSS or other libraries.

You can get more information about the base components from the below link

https://developer.salesforce.com/docs/component-library/bundle/lightning-avatar/example

Use Lightning Data Service (LDS)

Whenever there is a requirement to perform the DML operation using Lightning Web Component many developers use Salesforce Apex to do the DML.

We should always try to find an opportunity to use Lightning Data Service to perform any DML or Query any record which will improve the performance of your LWC and will be much faster than calling Apex.

Learn more about LDS from the below Link

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.data

Using Events In LWC

While you are working with multiple components and you are using components within another component ( concept of parent-child ).

There are various scenarios where we need to send the data back to the parent component from the child component and We should always use Custom Events and pass the required values.

Below is an example of sending the value to the Parent Component.

handleChange = (event)=>{
event.preventDefault();
this.value = event.target.value;
const selectedEvent = new CustomEvent('select', {
detail: {
value : this.value,
fieldApiName : this.picklistFieldApiName,
objectApiName : this.objectApiName,
indexVar: this.index
},
bubbles: false,
composed: false
});
this.dispatchEvent(selectedEvent);
}

There are some scenarios when you have nested components and the grandchild or great-grandchild wants to send some data to the grandparent component.

Many developers use bubbles & composed as false however it is recommended not to use these flags.

Always capture the event in the parent component and if needed then raise another event from the parent component to handle by the grandparent component.

Use @Api Decorator

@api decorators play a very important role when you wanted to send the data from the parent component to the child component or you wanted to take some inputs from the users while configuring the component inside

  1. Record Page
  2. Home Page
  3. FLow
  4. Inbox
  5. Community
  6. App Page & etc

Always take the advantage of the @api decorator and make the variables public that you wanted to expose outside of the component.

@Wire Decorator

@wire is the most powerful decorator in Lightning Web Component and we should be taking full advantage of this.

We can use the wire decorator in the below use cases –

  • Getting Read Only Records from Apex
  • Performing DML using LDS

Use RefreshApex In LWC

Say, for example, you have a list of records displayed in the lightning datatable, and the functionality of in-line editing is implemented there.

Now the requirement is whenever there are any changes in the record you want to display the latest value.

In most cases, developers will make a call to apex.

However, we should be using the LDS to perform the DML and refreshApex() method to refresh the records.

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_result_caching

Use Lightning Messaging Services (LMS)

When there is a requirement that the child component can send the data to the parent or grandparent you as a developer can/will use Custom Events however what if there is a requirement to set up the communication between 2 unrelated components that are on the Same Page.

OR If You wanted to set up the communication with unrelated AURA, VF, and LWC then how you will do this?

In these cases or scenarios, we will always use LMS which is the best fit for these cases with the combination of Platform Events, CDC & Streaming API.

Learn more about LMS from the below link

Use Spread Operator

The spread operator is a very powerful operator in JavaScript and we can use this to add any additional objects in an array or attributes in an Object.

Here are some examples of the same.

// add a new element in an arratlet obj = { name : 'value' }
obj = {
...obj,
email: 'amit@gmail.com'
}
console.log(obj);
// Add a new element in all the objects inside an arraylet fruits = [ {name:''}, {name:''}, {name:''}, {name:''}];let newArray = fruits.map(item => (
{
...item,
type :'demo'
}
)
);
console.log(newArray);

The spread operator can also be used to clone the object or array in JavaScript which will also be helpful in Lightning Web Component

Use JavaScript Array Functions

While working with Lightning Web Component, we are developing the JavaScript code most of the time and while we are using JS code we should always try to use the JavaScript functions which are given by the JS library. Some of the common used and important functions are given below

  • forEach
  • map
  • every
  • some
  • reduce
  • isArray
  • isNaN

Learn More from the below link

Avoid Hardcoding Ids & Static Values

If we do not use Hardcoding Ids and Static values in Apex we should also avoid using any hardcoding Ids or Static values in Lightning Web Components instead we should use Custom Labels for the same.

Error Handling Logic (Must Have)

The very important part of any Lightning Web Component. As a developer, we should always be having an Error Handling Logic in our Code and display the Proper Error Message using if:true and if:false.

You can either try catch in JavaScript or throw the proper error while calling the apex.

@wire(getObjectInfo, { objectApiName: '$objectApiName' })
wiredObject({ error, data }) {
if(data){
//console.log('wiredObject data: ', JSON.stringify(data) );
this.objectInfo = data;
if(!this.recordTypeId){
this.recordTypeId = data.defaultRecordTypeId;
}
}
if(error){
// Error Handling Logic Goes here....
console.error('wiredObject error: ' , JSON.stringify(error) );
this.objectInfo = undefined;
this.errorMessage = this.reduceErrors(error);
}
}

Display Loading Screen

Displaying the loading screen or spinner is also important and a must-have in any Lightning Web Component. If there are any apex calls being made we should be showing the spinner and hiding it once the call is completed.

To display the spinner we can use a lightning spinner base component and show/hide based on need.

Configure Meta Xml File In Right Way

When you wanted to use your Lightning Web Components at various places like app page, record page, flow &, etc then we should configure our meta.xml file properly and if required ask for the input parameters from Users.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>55.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__FlowScreen</target>
</targets>
<!-- Configuring the design attributes -->
<targetConfigs>
<targetConfig targets="lightning__HomePage,lightning__RecordPage">
<property name="picklistFieldApiName" type="String" label="Enter the picklist field api name" required="true" default="Active__c"/>
<property name="recordTypeId" type="String" label="Enter the Record Type Id" required="true" default="012000000000000AAA"/>
<property name="label" type="String" label="Enter the label to be displayed" required="true" default="Account Industry"/>
<property name="required" type="Boolean" label="Select if Input is required" description="Select if Input is required" />
</targetConfig>
<targetConfig targets="lightning__FlowScreen">
<property name="objectApiName" type="String" role="inputOnly" label="Enter the Object API Name" required="true" description="Enter the Object API Name" default="Account"/>
<property name="picklistFieldApiName" type="String" role="inputOnly" label="Enter the picklist field api name" description="Enter the picklist field api name" required="true" default="Active__c"/>
<property name="recordTypeId" type="String" role="inputOnly" label="Enter the Record Type Id" description="Enter the Record Type Id" required="true" default="012000000000000AAA"/>
<property name="label" type="String" role="inputOnly" label="Enter the label to be displayed" required="true" default="Account Industry"/>
<property name="required" type="Boolean" role="inputOnly" label="Select if Input is required" description="Select if Input is required" />
<property name="value" type="String" label="The Selected Value" role="outputOnly" description="The Selected Value" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>

Do Not Forget To Develop JEST Cases

last but not least we should always write the JEST cases for all our Lightning Web Components.

Learn more about JEST Cases here –

  1. https://developer.salesforce.com/docs/component-library/documentation/en/lwc/testing
  2. https://jestjs.io/

--

--

AMIT SINGH

Software Developer by day & YouTube by night. Salesforce Architect || Salesforce MVP || Integration Expert