Lightning Web Components and their Lifecycle Hook events

Lifecycle Hooks of Lightning Web Components:

Lightning web components have a lifecycle managed by the framework. The framework creates components, inserts them into the DOM, renders them, and removes them from the DOM. It also monitors components for property changes. 

Typically the lifecycle includes following steps:

  1. Component construction phase
  2. Component DOM insertion phase
  3. Component rendering phase
  4. Component error handling phase
  5. Component DOM removal phase
To understand the lifecycle in more detail, let's have a look at the following component structure which is based on Parent-Child relationship. This example will help to understand the exact flow of lifecycle of parent vs child.
Parent-Child Modal

By the end of this blog we will be able to understand
☞ Which component DOM is inserted first
☞ Different lifecycle hooks in Parent-Child modal and their execution
☞ Order in which they are removed from DOM.

Implementation:
Theory apart, let's design our components of interest.
  1. Parent Component: 
    containerComponent.html
    <template>
        <lightning-card>
            <lightning-layout class="slds-var-m-around_medium">
                <lightning-layout-item class="wide" style="width: 100%;">
                    <div class="slds-var-p-around_small">
                        <p>You're in container component.</p>
                        <c-child text={text}></c-child>
                    </div>
                </lightning-layout-item>
            </lightning-layout>
        </lightning-card>
    </template>
    containerComponent.js
    import { LightningElement } from 'lwc';
    
    export default class ContainerComponent extends LightningElement {
        text = 'You\'re in child component.';
    
        getChildElement() {
            let child = this.template.querySelector('c-child');
            console.log('child element in main component: ' + child);
        }
    
        constructor() {
            super();
            console.log('Constructor of main component is called.');
            console.log('text value in main constructor: ' + this.text);
            this.getChildElement();
        }
    
        connectedCallback() {
            console.log('ConnectedCallback of main component is called.');
            console.log('text value in main connectedCallback: ' + this.text);
            this.getChildElement();
        }
    
        renderedCallback() {
            console.log('RenderedCallback of main component is called.');
            console.log('text value in main renderedCallback: ' + this.text);
            this.getChildElement();
        }
    
        disconnectedCallback() {
            console.log('DisconnectedCallback of main component is called.');
            console.log('text value in main disconnectedCallback: ' + this.text);
            this.getChildElement();
        }
    
        errorCallback() {
            console.log('ErrorCallback of main component is called.');
            console.log('text value in main errorCallback: ' + this.text);
            this.getChildElement();
        }
    }
              
  2. Child Component: 
    child.html
    <template>
        <div class="slds-box">
            <span>{text}</span>
        </div>
    </template>
    child.js
    import { LightningElement, api } from 'lwc';
    
    export default class Child extends LightningElement {
        @api text;
    
        constructor() {
            super();
            console.log('Constructor of child component is called.');
            console.log('text value in child constructor: ' + this.text);
        }
    
        connectedCallback() {
            console.log('ConnectedCallback of child component is called.');
            console.log('text value in child connectedCallback: ' + this.text);
        }
    
        renderedCallback() {
            console.log('RenderedCallback of child component is called.');
            console.log('text value in child renderedCallback: ' + this.text);
        }
    
        disconnectedCallback() {
            console.log('DisconnectedCallback of child component is called.');
            console.log('text value in child disconnectedCallback: ' + this.text);
        }
    
        errorCallback() {
            console.log('ErrorCallback of child component is called.');
            console.log('text value in child errorCallback: ' + this.text);
        }
    }
Observation:
Let's deploy our code sample to home page of our app in our testing environment and look at the different phases of component lifecycle of this Parent-Child modal.
  1. Component construction phase: At this phase, the constructor() method is fired as component instance is being created. Don’t add attributes to the host element during construction. You can add attributes to the host element in any other lifecycle hook. This phase is from Parent to Child. Look at the result of construction phase. The flow starts from parent and until the parent is inserted in the DOM, there is no child element created. Also the construction phase doesn't allow to set up any attribute values and hence we are getting the text value as null in child component.
    Construction Phase(Parent to Child)

  2. Component DOM insertion phase: This is the second phase where the DOM insertion happens. This phase is also from Parent to Child. At this stage the connectedCallback() of Parent is fired ahead of Child. Note that the Child constructor() and connectedCallback() are fired after Parent DOM insertion(connectedCallback). Also look at the property text which is set after the connectedCallback of Child and not in the constructor of child. Also since the child is still not rendered, the child element in main component is still blank.
    DOM Insertion(Parent to Child)
  3. Component rendering phase: This is the most interesting phase of component lifecycle which is rendering of components. This time the child is rendered first and then the parent is rendered. This way, when the parent is rendered, you can now access the child element in the lifecycle.
    Rendering of Components(Child to Parent)

  4. Component DOM removal phase: This is the phase where the components start isolating from DOM and eventually go away. This phase is started from Parent meaning the Parent is removed first and then the child is removed.
    DOM Removal(Parent to Child)
To put everything, we have been through so far, in a nutshell, below describes the complete architecture of lightning web component's flow of execution or lifecycle.
Lifecyle Hooks

Cool, this completes the flow of lightning web components lifecycle and hope you have aced it now in understanding of how the flow starts and how it propagates. Stay tuned to more such amazing blogs going ahead.

If you like this blog content and find inciteful, please comment and let me know. 

Comments

  1. I have a question.
    you used super function in parent/child constructor why we are using that. Is it necessary to use them and if yes whose constructor these are calling

    ReplyDelete
    Replies
    1. Hello, that's very valid question and thanks for asking that.
      The answer to your first question is YES, we have to have this super function in the constructor of any LWC component if we are to use the constructor in that.
      Now to answer your second question WHY- Firstly we need to understand the basics of Lightning Web Components which are built upon modern web stack. Whenever we create any LWC Component, they are termed as Lightning Custom Element similar to HTML Custom Element on web stack. If you see the very first line in JS Class that extends the LightningElement, basically this is built on extending the HTMLElement which are custom element and calling constructor() of any custom element requires the super() constructor to be called for web stack with no parameters. This call establishes the correct prototype chain and value for "this". Always call super() before touching "this".

      You can refer to below links for more details:

      https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements

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

      Hope you should be clear with your question now.

      Delete
  2. It's really helpful. Example is so explanatory and flow is very understandable.

    ReplyDelete
  3. Really very nice content and helpful to understand concept of Lwc HookLifeCycle

    ReplyDelete

Post a Comment