It is frequently observed that developers often overlook the thorough examination of the Lightning Web Components (LWC) lifecycle. This tendency arises from the belief that merely incorporating the connectedCallback and renderedCallback addresses the issues. While this may solve problems, what about adhering to best practices? Given the novelty of LWC, it becomes crucial to understand the best practices associated with it.
Did you know that we also have a render callback designed specifically for loading templates? This blog incorporates a blend of practical proofs-of-concept (POCs) and theoretical insights, serving as your comprehensive guide to LWC lifecycle hooks.
constructor()
This method is invoked when the component is initially created. The execution flow of this method extends from the parent component to the child component. During this phase, accessing child elements within the component body is not possible since they do not exist at this point. Additionally, properties are not yet passed.
- connectedCallback()
This method is called when the element is inserted into a document. During this phase, the execution flow moves from the parent to the child. Accessing child elements within the component body is not feasible as they have not been created at this point.
- render()
Invoke this method to update the UI. It may be called either before or after. The parent is always rendered first in the flow. After rendering the parent, the flow transitions to the child’s constructor, following the same steps as the parent did previously until the child is rendered.
import { LightningElement,track } from 'lwc'; import signup from './signUp.html'; import login from './loginPage.html'; export default class LoginPage extends LightningElement { @track page=''; hasRendered=false; constructor(){ super(); } render(){ if(this.page==='temp1'){ this.hasRendered=true; return signup; }else{ this.hasRendered=true; return login; } } handleSignUp(){ this.page='temp1'; } handleLogin(){ this.page='temp2'; } back(){ this.page='temp2'; } afterSignUp(){ alert('refresh the page to login!'); } }
renderedCallback()
Executed after every rendering of the component, this hook generally follows the flow from the child component to the parent component, meaning from bottom to top. During this stage, the component undergoes re-rendering when the value changes, and that property is either directly used in a component template or indirectly in the getter of a property employed in a template.
- disconnectedCallback()
Invoked after every rendering of the component, this hook typically follows the flow from the child component to the parent component, progressing from bottom to top. In this phase, the component undergoes re-rendering when the value changes, and the property is either directly used in a component template or indirectly in the getter of a property used in a template.
- errorCallback()
This function captures errors that may occur in all child component lifecycle hooks. Unique to LWC, it takes two parameters: ‘error’ and ‘stack.’ The ‘error’ argument is a JavaScript native error object, and the ‘stack’ argument is a string.
Errors in the parent component are displayed in the UI without a boundary component. This means that if there is an error in the child, the parent handles it, but if there is an error in the parent, it is shown in the UI. This method functions similarly to a JavaScript catch()
block for catching errors.
How the page loads:
- Constructor of the parent gets called.
- Parent’s connectedCallback gets called.
- Render method gets called.
- Constructor of the child gets called.
- Child’s connectedCallback gets called.
- Child’s renderedCallback gets called.
- Parent’s renderedCallback gets called.
- Parent’s disconnectedCallback gets called.
- Child’s disconnectedCallback gets called.
Important considerations to prevent errors and conflicts:
Constructor:
- Avoid using a return statement inside the constructor body unless it is a simple early-return (return or return this).
- Do not use the
document.write()
ordocument.open()
methods. - Avoid inspecting the element’s attributes and children, as they don’t exist yet.
- Refrain from inspecting the element’s public properties since they are set after the component is created.
- Avoid adding attributes to the host element during construction.
ConnectedCallback:
- Use
connectedCallback()
to interact with a component’s environment. - Perform initialization tasks such as fetching data, setting up caches, or listening for events.
RenderedCallback:
renderedCallback()
updates a tracked (@track
) and wired (@wire
) property, triggering a render.- Use
renderedCallback()
to understand the state of the “inside” world, including a component’s UI and property state.
Render:
- Example: Consider a scenario with a parent component called Shapes and child components named Rectangle and Circle.
import { LightningElement,api } from 'lwc'; import firstTemplate from './rectangle.html'; export default class Rectangle extends LightningElement{ @api length; @api breadth; @api aor; constructor(){ super(); console.log('constructor-rectangle'); } connectedCallback(){ console.log('connectCallback-rectangle'); } renderedCallback(){ console.log('renderedCallback-rectangle'); } disconnectedCallback(){ console.log('disconnectedCallback-rectangle'); } finalAreaRectangle(){ this.aor=this.length*this.breadth; } render(){ return firstTemplate; } } import { LightningElement,api } from 'lwc'; import firstTemplate from './circle.html'; export default class Circle extends LightningElement{ @api radius; @api area; constructor(){ super(); console.log('constructor-circle'); } connectedCallback(){ console.log('connectCallback-circle'); } renderedCallback(){ console.log('renderedCallback-circle'); } disconnectedCallback(){ console.log('disconnectedCallback-circle'); } finalArea(){ this.area=3.14*this.radius*this.radius; } render(){ return firstTemplate; } } import { LightningElement } from 'lwc'; export default class Shapes extends LightningElement{ constructor(){ super(); console.log('constructor-shapes'); } connectedCallback(){ console.log('connectCallback-shapes'); } renderedCallback(){ console.log('renderedCallback-shapes'); } disconnectedCallback(){ console.log('disconnectedCallback-shapes'); } }
Output:
Thank you for taking the time to read this. Feel free to share your thoughts in the comments section below.
For additional Salesforce and MuleSoft tutorials, be sure to explore the Resource Centre at Caelius Consulting.