Lightning Components lifecycle

When working with Lightning Components framework it is very important to understand how the different components are rendered by the framework, which possibilities do we have to interact with the component lifecycle and how will the framework react to certain events as for example a change of an attribute. Want to know more? Continue reading!

When we navigate to a page in Lightning, the aura framework will be loaded. If we have a Lightning Component in this page, the server will send to the browser the information that is necessary to generate the component tree, this is, the components definition and instances. The aura framework will interprete this information to build the component tree. When the component tree is ready, the init event will be fired for all the components in the tree, and the component rendering lifecycle will start.

Note: If definitions were cached from a previous request, no server trip is done.

To illustrate all of this, I have created a hierarchy of nested components which full code you can check here.

Captura de pantalla 2018-04-22 a las 21.21.05

If you don’t want to check the full code, here you have a simplified version of the components markup so that you have an idea of how components are nested:

Parent.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String" />

    <c:child title="{!v.title}"/>
    <c:child2 title="{!v.title}"/>
</aura:component>

Child.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String"/>

    <c:grandson title="{!v.title}"/>
</aura:component>

Grandson.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String"/>

    {!v.title}
</aura:component>

Child2.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String"/>

    <c:grandson2 title="{!v.title}"/>
</aura:component>

Grandson2.cmp

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String"/>

    {!v.title}
</aura:component>

As you can see in the code, I have also created a handler for the init event on each of the components. The init handler looks like the next (replacing “XXXXX” by the name of each of the components in which we have defined the handler):

({
    doInit : function(component, event, helper) {
        console.log('XXXXX init - title: ' + component.get("v.title"));
    }
})

Also, I have defined renderers for all the components, in the next way:

({
    render : function(component, helper) {
        var ret = this.superRender();
    console.log('XXXXX render - title: ' + component.get("v.title"));
        return ret;
    },
    rerender : function(component, helper){
        this.superRerender();
        console.log('XXXXX rerender - title: ' + component.get("v.title"));
    },
    afterRender: function (component, helper) {
        this.superAfterRender();
    console.log('XXXXX afterRender - title: ' + component.get("v.title"));
    },
    unrender: function () { 
        this.superUnrender();
        console.log('XXXXX unrender');
    }
})

If we take a look at the chrome console once the component tree has been loaded in the page, it looks like this:

Captura de pantalla 2018-04-22 a las 21.27.27

This means that in the component lifecycle, first the init event will be called for each the components in the tree. We can listen to that event and perform any actions needed.

I have used Lightning Inspector to double check that the init events were being fired, and effectively they were 5 aura:valueInit events related to the components I have created:

 

In the case of having nested components, the init event will be fired first in the components that are lower in the hierarchy (child to parent), in a kind of discovery algorithm while going through the parent component markup.

Then, the rendering process will start, following exactly the same order. We can hook in this process defining a custom render() function.

Finally, we have another opportunity to hook in the rendering lifecycle, just after the component tree has been rendered, defining a custom afterRender() function. Again, the order in which this is executed is the same than in the previous cases.

As I wanted to check also how rerenders are performed automatically when attributes change, I decided to extend the use case, adding some buttons that will allow me to change the value of the title attribute.

abr-22-2018 20-44-27

When I load the component for the first time, title attribute is empty, so nothing is rendered in the grandson / grandson2 components.

When I click on the grandson2 component button, the attribute changes, and this change is transmitted to the whole hierarchy of nested components. This is what I obtain in the console:

Captura de pantalla 2018-04-22 a las 21.53.01.png

This time the order in which the nested components is rerendered has changed. It will go parent to child, in contrast with the previous cases.

In this case it is also very interesting to look at Lightning Inspector, as we can find out how the aura:valueChange event is propagated.

Captura de pantalla 2018-04-22 a las 22.37.07.png

As we can see a valueChange event is fired by the grandson2 component, and this event is propagated up in the hierarchy until reaching v.title, which is the attribute of the parent component. At the same time, in each of the intermediate steps, the changes are propagated down to any other child branch in the hierarchy.

Then I click on the parent component button and this is what I obtain:

captura-de-pantalla-2018-04-22-a-las-21-56-06.png

And we obtain again the same order.

In this case, the events are only propagated down in the hierarchy:

Captura de pantalla 2018-04-22 a las 22.49.32.png

Note: although in this example I have used bidirectional data binding, take a look at one of my previous posts in which I explained how to make your components more performant thanks to unbound expressions and one way binding.

Leave a Reply

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 )

Google+ photo

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

Twitter picture

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

Facebook photo

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

w

Connecting to %s