LitElement renders and re-renders asynchronously, updating in response to batched property changes (see Element update lifecycle for more information).

During an update, only the parts of the DOM that change are re-rendered. To get the performance benefits of this model, you should design your element's template as a pure function of its properties.

To do this, make sure the render function:

Also, avoid making DOM updates outside of render. Instead, express the element's template as a function of its state, and capture its state in properties.

The following code uses inefficient DOM manipulation:

dom-manip.js

// Anti-pattern. Avoid!

constructor() {
  super();
  this.addEventListener('stuff-loaded', (e) => {
    this.shadowRoot.getElementById('message').innerHTML=e.detail;
  });
  this.loadStuff();
}
render() {
  return html`
    <p id="message">Loading</p>
  `;
}

We can improve the template by capturing the load message as a property, and setting the property in response to the event:

update-properties.js

constructor() {
  super();
  this.message = 'Loading';
  this.addEventListener('stuff-loaded', (e) => { this.message = e.detail } );
  this.loadStuff();
}
render() {
  return html`
    <p>${this.message}</p>
  `;
}

{% include project.html folder="docs/templates/design" openFile="update-properties.js" %}