kit icon indicating copy to clipboard operation
kit copied to clipboard

SvelteKit 2: Shallow Routing / Browser Navigation Fails to Reopen Modal and Route

Open m345054 opened this issue 1 year ago • 2 comments

Describe the bug

In SvelteKit, after opening and closing a post modal via browser navigation (back and forward buttons), the state or parameters fail to update correctly. While the URL reflects the navigated page, the post modal does not reopen as expected.

Reproduction

https://github.com/m345054/sveltekit-shallow-routing-bug-report

  1. Load the '/' page.
  2. Open any post to view the modal.
  3. Use the browser's back button to return to '/' and close the modal.
  4. Use the browser's forward button to attempt to reopen the modal.

Expected Behavior: The post modal should reopen upon navigating forward.

Actual Behavior: The URL changes, but the modal does not reopen.

This issue also appears when starting from a child page

  1. Load the '/[id]' page (e.g. '/2')
  2. Use svelte button to go to '/'
  3. Use brower's forward button to attempt to reopen the route.

Logs

No response

System Info

System:
    OS: Windows 11
  Binaries:
    Node: 20.10.0
    npm: 9.6.2
  Browsers:
    Chromium: 120.0.6099.199
    Firefox: 121.0
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.1.0
    @sveltejs/kit: ^2.0.0 => 2.0.6
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.0.1
    svelte: ^4.2.7 => 4.2.8
    vite: ^5.0.3 => 5.0.11

Severity

critical

Additional Information

  • Console logs for $page.state and $page.params do not update as expected when using the browser's forward button.
  • Issue occurs regardless of SSR state.
  • Direct manipulation with pushState('', { id }); works but does not change the URL as I need for my project.

m345054 avatar Jan 05 '24 16:01 m345054

Can confirm, I ran into this aswell

david-plugge avatar Jan 05 '24 23:01 david-plugge

Seems to be related to #11492

m345054 avatar Jan 08 '24 21:01 m345054

I ran into a similar issue, wondering if anyone else has seen this behavior. I have a modal I want to open on initial page load, so I have something like

onMount(() => {
  pushState('', { modalOpen: true });
});

This initially seems to work, the modal appears on page load, but then the +layout.svelte load promise settles, which seems to reset the $page.state variable. I added some logging, and the order of events is

page mounted

modal opens

layout.load settles

modal closes

jessecoleman avatar Jan 15 '24 01:01 jessecoleman

@jessecoleman You should probably use afterNavigate instead of onMount.

PatrickG avatar Jan 31 '24 12:01 PatrickG

@jessecoleman You should probably use afterNavigate instead of onMount.

Thanks. I think I figured out my issue, which was maybe unrelated to this bug. When calling invalidate on a page, the $page.state gets reset. I found a workaround but I still don't know if this is a bug. I came up with a minimum reproduction if you want to look into this further: https://github.com/jessecoleman/sveltekit-shallow-routing-bug-report

The crux:

  import { invalidateAll, pushState } from "$app/navigation";
  import { page } from "$app/stores";
  import { onMount } from "svelte";

  onMount(async () => {
    await new Promise(resolve => 
      // some latency in network before state changes
      setTimeout(() => {
        pushState('', { id: 123 })
        resolve(null);
      }, 1000)
    )
    // some more latency in network before calling invalidateAll
    await new Promise(resolve => 
      setTimeout(() => {
        invalidateAll();
        resolve(null);
      }, 1000)
    );
  });

</script>```
After the second promise settles and the `layout.server` `load()` reruns, the original `$page.state` is not set. 

jessecoleman avatar Feb 06 '24 01:02 jessecoleman

@jessecoleman #11783

PatrickG avatar Feb 07 '24 10:02 PatrickG