Design a site like this with WordPress.com
Get started

Dynamic and Reactive Javascript Class Properties in LWC (track, wire and $)

Consider a scenario: When text is entered in input, it should search accounts with that search text.

poc.html

<template>
	<lightning-input onchange={doSearch} value={accName}></lightning-input>

	<template if:true={accs.data}>
		<template for:each={accs.data} for:item='pd'>
			<div key={pd.Id} class="slds-box">
				<lightning-formatted-text value={pd.Name}></lightning-formatted-text>
			</div>
		</template>
	</template>
	<template if:true={accs.error}>ERROR => {accs.error}</template>

</template>

Below is the Javascript of poc component:

poc.js

import { LightningElement, track, wire } from 'lwc';
import getAccounts from '@salesforce/apex/poc.getAccounts';

export default class Poc extends LightningElement {
	@track accName;
	@wire(getAccounts, { accName: '$accName' })
	accs;

	getAccName(event) {
		this.accName = event.detail.value;
	}
	renderedCallback() {
		console.log("RENDERED POC");
	}
}

As you observe, we are logging “RENDERED POC” everytime it rerenders.

poc.class

@AuraEnabled(cacheable=true)
    public static List<Account> getAccounts(String accName){
        return [SELECT Id, Name FROM Account WHERE Name LIKE :('%'+accName+'%')];
    }

What will happen when you enter something?

accName will get updated in getAccName method AND component immediately rerenders (as accName is tracked property) and this can be observed in log. ‘$accName’ is dynamic and reactive property. Change in accName will trigger the wire function which is dependent on ‘$accName’ and wire will modify the value of accounts which is tracked property. Thus the component rerenders again! This may lead to performance degradation.

So, what can we do?

  1. Do not track dynamic properties.
  2. Remove the references of dynamic properties in html and use separate tracked properties.

Remove accName from input. In any case, that value doesnt get updated directly. We need to update accName in change handler. If we want to prepolute input, we should use separate tracked property.

<lightning-input onchange={getAccName}></lightning-input>

In javascript, do not track accName.

export default class Poc extends LightningElement {
	@wire(getAccounts, { accName: '$accName' })
	accs;

	getAccName(event) {
		this.accName = event.detail.value;
	}
	renderedCallback() {
		console.log("RENDERED POC");
	}
}

Now load the page and start search again. You will observe that component will rerender only once instead of 2 times for each search.

Reason: As accName is referred dynamically in wire, a change in accName will automatically trigger the wire function and thus it will update accounts.

Advertisement

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: