lwc icon indicating copy to clipboard operation
lwc copied to clipboard

Synthetic lifecycle observable changes when slotted into native lifecycle

Open nolanlawson opened this issue 1 month ago • 0 comments

TL;DR: No matter what, there will be some observable difference if a synthetic-lifecycle component is slotted into a native-lifecycle component.

As demonstrated by #4248, we have some issues where we have incorrect behavior when a synthetic lifecycle component is slotted into a native lifecycle component. In particular, its disconnectedCallback may be invoked without a corresponding connectedCallback (for a true case of disconnect+reconnect).

We can fix these bugs, but I think there will still be cases where we can't perfectly emulate the old pure-synthetic-lifecycle behavior for synthetic-lifecycle components in a mixed context. For example:

<!-- slottable.html -->
<template lwc:if={foo}>
  <slot></slot>
</template>
// slottable.js
renderedCallback() {
  this.foo = true
}
<!-- container -->
<x-slottable> <!-- native lifecycle -->
  <x-slottee></x-slottee> <!-- synthetic lifecycle -->
</x-slottable>

In this case, a synthetic-lifecycle component is being slotted into a native-lifecycle component. However, the outer component is changing its state within its renderedCallback, which affects how the inner component is mounted/unmounted. (I used renderedCallback, but I could have also used disconnectedCallback/connectedCallback.)

The point is that the outer component has changed the timing of its state changes due to native lifecycle. Necessarily, the inner component will be unmounted/mounted based on the native timing, not the synthetic timing it expects. For example, the outer component could be inside of a list which is re-sorted, triggering a disconnect+reconnect, which the inner component may not be expecting.

So no matter what, there will be some observable difference if a synthetic-lifecycle component is slotted into a native-lifecycle component.

nolanlawson avatar Jun 02 '24 16:06 nolanlawson