lit / lit-element

LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.
https://lit-element.polymer-project.org
BSD 3-Clause "New" or "Revised" License
4.49k stars 318 forks source link

Property update triggers an update cycle even if element is disconnected #1083

Closed madfriend closed 3 years ago

madfriend commented 3 years ago

Description

After an element is disconnected from the DOM, any property update still triggers an update cycle.

Live Demo

https://stackblitz.com/edit/lit-element-example-raltka?file=index.html

Steps to Reproduce

  1. Create my-element
  2. Set the mood property (update cycle doesn't start)
  3. Append my-element to document.body
  4. Set the mood property again - update cycle starts
  5. Remove my-element from document.body
  6. Update the mood property.

Expected Results

Update cycle is not started and shouldUpdate is not called. (Same as before element is connected)

Actual Results

Update cycle starts and shouldUpdate is called.

Browsers Affected

I've tested in Chrome only, but the bug shouldn't be browser-specific.

Versions

litelement: 2.4.0 webcomponents: 2.4.4

sorvell commented 3 years ago

This behavior is by design. While it's probably fair that most elements shouldn't update when they are disconnected, we're uncomfortable baking in that assumption. It's true that LitElement does wait until connectedCallback to start the update cycle; however, this is really only done to work around a platform limitation that makes connectedCallback the first reliable spot to ensure all of an element's attributes have run through attributeChangedCallback.

This is also behavior that should be fairly easy to customize in a base class if you want. Something like:

shouldUpdate() {
  // record if a disconnected update was attempted
  this.disconnectedUpdate = !this.isConnected;
  // only update if connected
  return this.isConnected;
}

connectedCallback() {
  super.connectedCallback();
  if (this.disconnectedUpdate) {
    this.requestUpdate();
  }
}