lit / lit

Lit is a simple library for building fast, lightweight web components.
https://lit.dev
BSD 3-Clause "New" or "Revised" License
18.41k stars 911 forks source link

Challenges with hostUpdate and hostUpdated when Using addController in LitElement #4445

Open a7medm7med opened 8 months ago

a7medm7med commented 8 months ago

Should this be an RFC?

Which package is this a feature request for?

Lit Core (lit / lit-html / lit-element / reactive-element)

Description

I'm currently working on a project where I am using the addController method to add a reactive controller to a Lit component. However, I've encountered an issue with the hostUpdate and hostUpdated methods not receiving the changed props as expected.

I've consulted the official documentation and haven't found a clear solution to this problem. I'm wondering if there's a known issue or if I might be overlooking something in my implementation.

I expected hostUpdate and hostUpdated to receive the changed props, but it seems that this is not happening. Is there a recommended way to ensure these methods have access to the changed props when using controllers?

Alternatives and Workarounds

Ensuring Reactive Controller Lifecycle Methods Have Access to Changed Props

sorvell commented 8 months ago

Thanks for the issue. The changedProperties are currently not passed to hostUpdate/hostUpdated, and although making them available has been discussed, it's been a little controversial.

Without changedProperties, you will need to manually track changes in a controller from update to update by reading off of the host itself.

hostUpdate() {
  if (this.previousHostProp !== this.host.prop) {
    // do thing
   this.previousHostProp= this.host.prop;
  }
}

The concern with exposing changedProperties is essentially that it has the potential to make the controller and host element too coupled.

djthorpe commented 4 months ago

I'd argue that the coupling between the controller and the host is currently too weak. In a classical Model/View/Controller pattern the controller needs to be able to update the view depending on changes in the model, and vice-versa.

Potentially it would be good to signal a controller when addController is called on a host, or alternatively just pass the host into hostUpdate.

At the moment, the only way to link a host to a controller is through the constructor function, but addController can also work in other parts of the lifecycle.

As previous sugesstions imply, passing the host object to hostUpdate and hostUpdated would be useful, especially where a controller is managing more than one host. Ie,

hostUpdate(host) {
  if (this.previousHostProp[host] !== host.prop) {
    // do thing
   this.previousHostProp[host] = host.prop;
  }
}

Would it be too much to also suggest calling hostUpdate as part of the addController process, to initialize the properties in the controller.