kit
kit copied to clipboard
SvelteKit 2: Shallow Routing / Browser Navigation Fails to Reopen Modal and Route
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
- Load the '/' page.
- Open any post to view the modal.
- Use the browser's back button to return to '/' and close the modal.
- 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
- Load the '/[id]' page (e.g. '/2')
- Use svelte button to go to '/'
- 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.
Can confirm, I ran into this aswell
Seems to be related to #11492
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 You should probably use afterNavigate instead of onMount.
@jessecoleman You should probably use
afterNavigateinstead ofonMount.
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 #11783