juliocastillo.dev YaDS - Yet another Developer's Site

LitElement in depth: the update lifecycle

LitElement

📣 UPDATE! 📣 Now lit-html and LitElement are unified under Lit. I'm writing new posts about Lit, meanwhile you can:

  • read this post because the principles are the same
  • upgrade your code with this [guide] (https://lit.dev/docs/releases/upgrade/)
  • visit Lit site to know what's new

You can also use lit-html standalone

Although lit-html is very efficient rendering, it is better to render only when necessary. That is why LitElement differs the re-rendering of the UI by batching the property updates. In other words, re-rendering is done asynchronously to ensure efficiency and good performance. Let's see how the update process works.

Recall from the previous post that all the properties defined in the properties getter become properties "controlled" by LitElement.

For each property defined in the properties getter, LitElement will generate:

In particular, we are interested in the hasChanged function and the setters because they play an important role in the update life cycle.

Almost all the "magic" is based on the setter that causes the component to be re-rendered when the property changes. First, it checks if the property has changed (invoking the hasChanged function) and, if that is the case, it will make a rendering request. Also, if the property is reflected in an attribute, the setter will update the observed attribute using the toAttribute function.

In the LitElement class we find the following methods that participate in the update of the UI:

Now that we have seen the main pieces involved in the re-rendering, we will go into detail on how this process occurs.

The update cycle in action

Imagine you have a function with this piece of code:

const el = document.querySelector('#myElement');
el.title = 'Movements'; //previous value was 'No title'
el.icon = 'book.ico'; //previous value was undefined
await el.updateComplete;

Alt Text

👉 All the properties defined in the properties getter become properties "controlled" by LitElement and any update of their values ​​will cause a rendering. This is why we should put there only the properties that affect the visual representation of the component: those that we have used in the template. For example, if we have a debug property that is used to indicate if traces are written by console.log, changing this property should not cause an UI update.

Live example

To understand it better, I have made this very silly component. The important part is that I have traced each method of the update lifecycle.

{ % stackblitz litelement-update-cycle % }

requestUpdate

Sometimes it may be necessary to manually trigger the re-rendering cycle. It is not enough to invoke the render method, because as we have seen, the process is much more complex. For these cases, LitElement provides the requestUpdate method that will trigger the whole lifecycle update.

A typical case where we should invoke requestUpdate is when we define our own setter and we want that a change in the property to cause a re-rendering. As we have seen before, for each controlled property LitElement generates a setter that evaluates whether the property has changed and if so, it updates the UI. But when we write our own setter, we lose the setter that would be generated by LitElement, because of this, we have to do by ourselves what LitElement does. We should do:

set title(value) {
if (this._title !=== value) {
const oldValue = this._title;
this._title = value;
this.requestUpdate('title', oldValue); // Called from within a custom property setter
}
}

👉 When we invoke requestUpdate from a setter we must pass the property name and the old value as arguments. On the other hand, if we force a re-render from elsewhere, requestUpdate has no arguments.

This is the end

With this last topic about the UI update lifecycle we complete the basics of LitElement. You already have the fundamental knowledge to continue your path in lit-html and LitElement.

To go deeper in these libraries I highly recommend reading the official documentation. It's It is very clear, concise and very well organized. In addition, each topic is accompanied by a live example in Stackblitz.

I also suggest you read the source code of lit-html and LitElement. It is relatively short, well documented and with what you already know you will not find it difficult to understand. This way everything will be much clearer.

Last but not least, two important contributions from the community:

Last words...

With this post I finish my series on LitElement. I hope you found it useful and enjoyed it as much as I did writing it. Thank you for having come this far! ❤️

comments powered by Disqus