sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
79.81k stars 4.24k forks source link

Invalidation during parent `out:`, can cause child `in:` to play, or `out:` to stall #9198

Closed robertadamsonsmith closed 5 days ago

robertadamsonsmith commented 1 year ago

Describe the bug

There are two related bugs. During an outro in a parent component, if the child component has a variable invalidated which an #if block is dependant on, and the #if block contains an element with its own transition, then either:

(REPLs below)

There are several issues that are ultimately due to this, and I've encountered both bugs myself, so I think it could be quite widespread: https://github.com/sveltejs/svelte/issues/8606 https://github.com/sveltejs/svelte/issues/8351 https://github.com/sveltejs/svelte/issues/5268 https://github.com/sveltejs/svelte/issues/9186

It appears that the first bug occurs because when the transition is |local the generated fragment doesn't track current so that when the up()date function calls transition_in, it is unable to early exit the i()ntro. It does actually do that correctly when |global is used though, so it might just be a case of using that logic more generally.

I'm not yet sure why the second bug is occurring, but I assume the logic is highly related.

Reproduction

This is the minimal test case that demonstrates the first behaviour: https://svelte.dev/repl/b558e1303d1f45848b4dffc765c806dc?version=4.2.0

App.svelte

<script>
    import Child from "./Child.svelte"
    import {fade} from "svelte/transition"
    import {writable} from "svelte/store"

    let state = writable({});
    let show = true;

    function toggle() {
        $state = {};
        show = !show;
    }
</script>

<button on:click={toggle}>Toggle</button>

{#if show}
    <div transition:fade>
        Parent
    </div>  
    <Child {state} />
{/if}

Child.svelte

<script>
    import {fade} from "svelte/transition"

    export let state;
</script>

{#if true || $state}
    <div transition:fade>
        Child
    </div>
{/if}

The requirements are as follows:

The second bug can be demonstrated by just changing the Child transition to |global: https://svelte.dev/repl/74b66e56366c491baf37f4baa4a1c347?version=4.2.0

This has the following effect:

Logs

No response

System Info

4.2.0

Severity

annoyance

tschortsch commented 10 months ago

We experience the exact same bug while using the |global modifier in the transition. Are there any updates on this issue or does a workaround exist? (of course expect removing all transitions 😉)

dummdidumm commented 5 days ago

Fixed in Svelte 5