kit icon indicating copy to clipboard operation
kit copied to clipboard

Layout with transition not unmounted on navigation

Open hyunbinseo opened this issue 1 year ago • 10 comments

Describe the bug

When routing from /b to / using an anchor element, the /b/+page.svelte component does not get unmounted.

<!-- /routes/b/+layout.svelte -->

<script>
  import { page } from '$app/stores';
  import { slide } from 'svelte/transition';

  $: isB = $page.url.pathname === '/b';
</script>

<slot />
{#if isB}
  <div transition:slide><a href="/">Home</a></div>
{/if}
<!-- /routes/b/+page.svelte -->

<div><a href="/">Home</a></div>
  • Expected behavior: all /routes/b related components should be unmounted.
  • Actual behavior: the <div><a href="/">Home</a></div> component remains.

Reproduction

Check Stackblitz

Instructions

  1. Press /b
  2. Press /a

Expected behavior

/a

/b - /a/+page.svelte

Actual behavior

/a

/a - /b/+page.svelte
/b - /a/+page.svelte

Logs

No response

System Info

System:
  OS: Windows 10 10.0.22621
  CPU: (8) x64 AMD Ryzen 7 4700U with Radeon Graphics
  Memory: 3.79 GB / 15.32 GB

Binaries:
  Node: 18.12.0 - C:\Program Files\nodejs\node.EXE
  npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD

Browsers:
  Edge: Spartan (44.22621.675.0), Chromium (105.0.1343.53)
  Internet Explorer: 11.0.22621.1

Severity

annoyance

Additional Information

  • https://github.com/sveltejs/kit/issues/3753#issue-1125425183

hyunbinseo avatar Oct 27 '22 03:10 hyunbinseo

While waiting for a fix, you can workaround this by adding local to the transition:

<script>
  import { page } from '$app/stores';
  import { slide } from 'svelte/transition';

  $: isB = $page.url.pathname === '/b';
</script>

<slot />
{#if isB}
-   <li transition:slide><a href="/a"><code>/a</code></a> - <code>/b/+layout.svelte</code></li>
+  <li transition:slide|local><a href="/a"><code>/a</code></a> - <code>/b/+layout.svelte</code></li>
{/if}

But either way, a very interesting bug. I've had similar troubles with navigation and using transitions, but adding local usually fixes them. However, it's still confusing when it happened to me while I was learning Svelte.

eltigerchino avatar Oct 27 '22 07:10 eltigerchino

+1, but not using a transition. Seeing subsequent pages mount under the previous page. Like, at the bottom of the page. The +layout and +page of the previous page is never unmounted.

Screen Shot 2022-11-02 at 11 32 06 AM Screen Shot 2022-11-02 at 11 32 16 AM

mglikesbikes avatar Nov 02 '22 16:11 mglikesbikes

+1, but not using a transition. Seeing subsequent pages mount under the previous page. Like, at the bottom of the page. The +layout and +page of the child page is never unmounted.

Are you able to identify the cause? Personally curious

eltigerchino avatar Nov 02 '22 16:11 eltigerchino

Are you able to identify the cause? Personally curious

nope.

mglikesbikes avatar Nov 02 '22 16:11 mglikesbikes

Update: found some transitions buried in a component I forgot about 😅 adding the |local modifier fixed this for me.

In tracking it down, looked like something between @sveltejs/kit version 521 and 522 is the culprit. v521 worked fine, v522 = layout hell.

mglikesbikes avatar Nov 02 '22 17:11 mglikesbikes

I have made a reproducible example (albeit a bit bigger than needed) if you want to play with it: https://stackblitz.com/edit/sveltejs-kit-template-default-1fsbnb

Melkaz avatar Nov 09 '22 18:11 Melkaz

I can't track this down to a recent kit version, going back as far as 450 still reproduces this. I think the issue lies in Svelte core. I can reproduce this with a simple variable that is updated every 10 miliseconds. My guess is that updating the value while transitioning out breaks things.

<script>
  import { slide } from 'svelte/transition';

  let foo = {t:true}
  setInterval(() => foo={t:true}, 10);
</script>

<slot />
{#if foo.t}
  <li transition:slide><a href="/a"><code>/a</code></a> - <code>/b/+layout.svelte</code></li>
{/if}

https://stackblitz.com/edit/sveltejs-kit-template-default-8n1tyl?file=package.json,src%2Froutes%2F%2Blayout.svelte,src%2Froutes%2Fb%2F%2Blayout.svelte

dummdidumm avatar Nov 17 '22 10:11 dummdidumm

possibly related - #7877

Tal500 avatar Nov 29 '22 12:11 Tal500

Pls Fix!

jkrocks47 avatar May 26 '23 00:05 jkrocks47

ugh, just ran into this. very strange bug. pls fix!

benwoodward avatar Jun 01 '23 08:06 benwoodward

I also noticed that one of my pages took 500ms to disappear when navigating out. I tracked it to a component I was using which was using a transition that was not local. In Svelte 3 and earlier, apparently, the default is global. I think they must have recognized that this is a bad default. Svelte seems very ambitious, but somehow not quite there yet.

godmar avatar Nov 16 '23 06:11 godmar

I can't track this down to a recent kit version, going back as far as 450 still reproduces this. I think the issue lies in Svelte core. I can reproduce this with a simple variable that is updated every 10 miliseconds. My guess is that updating the value while transitioning out breaks things.

<script>
  import { slide } from 'svelte/transition';

  let foo = {t:true}
  setInterval(() => foo={t:true}, 10);
</script>

<slot />
{#if foo.t}
  <li transition:slide><a href="/a"><code>/a</code></a> - <code>/b/+layout.svelte</code></li>
{/if}

stackblitz.com/edit/sveltejs-kit-template-default-8n1tyl?file=package.json,src%2Froutes%2F%2Blayout.svelte,src%2Froutes%2Fb%2F%2Blayout.svelte

It seems to be fixed with Svelte 5. Here's an updated repro. I just updated all dependencies to their latest.

eltigerchino avatar Nov 16 '23 12:11 eltigerchino

While there may be multiple issues at play (see the many bug reports dealing with transitions), let me clarify what I believe I encountered.

If a Svelte 3 page/layout uses a third-party component (such as svelte-video-player in my case) which internally uses a non-local transition on any of its components, then this transition plays when the page contained the component is destroyed - this is probably as it should be, although likely the developer of the component didn't intend this, and it's creating problems for the user of the component because they have no way to override the transition (let alone that it's confusing and takes a long time to figure out).

But what's clearly a bug (in Svelte 3, probably) is this: not only does the transition play (and delay the hiding of the page that the component is in), but the new page that's being navigated to has already appeared even before all components in the old page have been transitioned out. It appeared under the previous one as described by @mglikesbikes. In my case, the old page/layout did eventually disappear after playing its transition (so this may not be quite the bug described here where the old page doesn't get destroyed at all).

I think the reason they made transitions local by default in Svelte 4 may be this, which is to avoid such unintended effects of components on the pages/layouts containing them.

godmar avatar Nov 16 '23 16:11 godmar