lwc
lwc copied to clipboard
Synthetic lifecycle observable changes when slotted into native lifecycle
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.