sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.73k stars 1.95k forks source link

Layout with transition not unmounted on navigation #7405

Closed hyunbinseo closed 6 days ago

hyunbinseo commented 2 years ago

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>

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

eltigerchino commented 2 years ago

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.

mglikesbikes commented 2 years ago

+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
eltigerchino commented 2 years ago

+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

mglikesbikes commented 2 years ago

Are you able to identify the cause? Personally curious

nope.

mglikesbikes commented 2 years ago

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.

Melkaz commented 2 years ago

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

dummdidumm commented 2 years ago

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

Tal500 commented 1 year ago

possibly related - #7877

jkrocks47 commented 1 year ago

Pls Fix!

benwoodward commented 1 year ago

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

godmar commented 1 year ago

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.

eltigerchino commented 1 year ago

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.

godmar commented 1 year ago

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.

eltigerchino commented 6 days ago

Closing as fixed in svelte 5