Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: fix light dom slots for fragments #3824

Merged
merged 12 commits into from
Oct 27, 2023
Merged

Conversation

jmsjtu
Copy link
Member

@jmsjtu jmsjtu commented Oct 21, 2023

Details

Partially fixes #3823, the synthetic lifecycle will not call disconnectedCallback but does bring it back to parity with the behavior from LWC 3.x.x.

A followup PR will fully resolve #3823.

Does this pull request introduce a breaking change?

  • ✅ No, it does not introduce a breaking change.

Does this pull request introduce an observable change?

  • ⚠️ Yes, it does include an observable change.

This will allow disconnectedCallback to be invoked for light DOM slots, which was merged today so it shouldn't have a large impact.

@jmsjtu jmsjtu requested a review from a team as a code owner October 21, 2023 04:05
Comment on lines 337 to 349
it('regression test (#3827) - light DOM should maintain callback invocation order for duplicate slots across conditional branches when rerender triggered on conditional slot component', () => {
// #TODO[3827]: These regression tests can be removed once the bug is resolved.
const container = createElement('x-light-container-multiple-conditionals', {
is: LightContainerMultipleConditionals,
});
document.body.appendChild(container);

let currentLeafName = container.getLeaf().name;
expect(window.timingBuffer).toEqual([
'lightContainer:connectedCallback',
'lightSlot:connectedCallback',
`leaf:${currentLeafName}:connectedCallback`,
]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are a little strange, but I created them to capture the current behavior and ensure they match what happens in 3.x.x.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this bug only occurs if the conditional rendering occurs on the same component as the <slot> element.

The bug also only occurs when the condition is only triggered through the component containing the <slot>.

If the condition depends on a value being passed from a parent component, the slots will render correctly.

Copy link
Collaborator

@nolanlawson nolanlawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, since the behavior is the same as v3.x.

Since we have API versioning tests, and since the tests pass the same in both versions, we know this must be true! 😄

: [
`leaf:${currentLeafName}:connectedCallback`,
`leaf:${currentLeafName}:disconnectedCallback`,
]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the previous leaf never fires a disconnectedCallback? I thought this was the entire bug?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nolanlawson yup, the previous leaf won't fire disconnectedCallback in synthetic lifecycle.

This is how it behaves in 3.x.x, this PR just brings the behavior back to what it was in 3.x.x.

I plan to raise another PR to fix the disconnectedCallback behavior entirely as part of #3832

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to raise another PR to fix the disconnectedCallback behavior entirely

Is this worth doing if we are going to do native lifecycle in 5.0?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think either way this will need to be fixed because if you look at the native lifecycle (one above this one) the new component is connected and immediately disconnected.

Which means all the components are disconnected after unmount runs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is a very specific bug, the rerender has to be isolated to just the component containing the <slot> element.

For example:

<template>
    <template lwc:if={showMe}>
        <slot></slot>
    <template lwc:else>
        <slot></slot>
</template>

If the value of showMe is passed down from a parent component then this bug does not appear, but if the value of showMe is isolated to just the component, it does.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think either way this will need to be fixed because if you look at the native lifecycle (one above this one) the new component is connected and immediately disconnected.

So is the issue that the diffing algo is doing extra unnecessary work?

Copy link
Member Author

@jmsjtu jmsjtu Oct 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort of, in this specific bug, the references to what's being slotted is getting mixed up, so when the element is removed from the DOM the native lifecycle is called on the old component and the synthetic lifecycle is called on the new component.

@jmsjtu jmsjtu merged commit 20dcd5c into master Oct 27, 2023
7 checks passed
@jmsjtu jmsjtu deleted the jtu/fix-lightdom-slot branch October 27, 2023 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Light Dom slots don't trigger disconnectedCallback in synthetic lifecycle
2 participants