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

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

Open
robertadamsonsmith opened this issue Sep 13, 2023 · 1 comment

Comments

@robertadamsonsmith
Copy link

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:

  • if the transition is |local, the intro transition will unexpectedly start playing
  • if the transition is |global, the parents outro will very unexpectedly stall at the end, leaving all elements visible and unmounted

(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: #8606 #8351 #5268 #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:

  • There must be a parent and child component (if the child is inlined into the parent, the bug does not occur)
  • The parent must have a conditional block which becomes falsy, containing both a transition: element, and the child component
  • While the parent component's outro is playing (or at the same time as it starts), a variable in the child component must become invalidated. This is typically done by having a shared store be updated with a non-primitive value (but could also be from some other mechanism, such as calling a function exported from the child component that invalidates a value within the component to a non-primitive value)
  • The child component must have a conditional block which is apparently dependent on the invalidated variable, and which contains a transition: element (note that the conditional block can even be 'fixed' to always be true, so the value of the variable doesn't matter, only that it has been invalidated)
  • The child component's element will now start playing its intro transition

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:

  • When the outro finishes, all elements that should have been removed remain mounted and visible
  • The child component's element won't play its intro transition though (silver linings)

Logs

No response

System Info

4.2.0

Severity

annoyance

@tschortsch
Copy link

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 😉)

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

No branches or pull requests

2 participants