sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.46k stars 1.89k forks source link

beforeNavigate hook loses search parameters present in the URL after successive navigations #10122

Open Benaiah opened 1 year ago

Benaiah commented 1 year ago

Describe the bug

I am trying to use beforeNavigate to preserve a query parameter in the URL if it is present. The important bit is as follows, in the root +layout.svelte file:

<script>
  import { beforeNavigate } from "$app/navigation";
  const paramName = "test";
  beforeNavigate(({ from, to }) => {
    const previousParamValue = from?.url.searchParams.get(paramName);
    if (typeof previousParamValue === "string") {
      to?.url.searchParams.set(paramName, previousParamValue);
    }
  })
</script>

<slot />

Now, if I run npm run dev and visit localhost:5173?test=true and start navigating between pages, the test param will be preserved for the first navigation, but not for navigations after that. This is because the from value passed to the beforeNavigate callback does not contain the query parameters that are in the actual URL for navigations after the first one following the query parameter being added.

The navigating store from $app/stores exhibits the same problematic behavior.

The workaround is relatively simple:

<script>
  import { beforeNavigate } from "$app/navigation";
  import { page } from "$app/stores";
  const paramName = "test";
  $: lastPageURL = $page?.url;
  beforeNavigate(({ to }) => {
    const previousParamValue = lastPageURL?.searchParams.get(paramName);
    if (typeof previousParamValue === "string") {
      to?.url.searchParams.set(paramName, previousParamValue);
    }
  })
</script>

<slot />

Reproduction

Repro repository: https://github.com/Benaiah/repro-svelte-navigation-hook-bug

Instructions:

The logs attached are a copy of the console logs in the browser as this process is followed.

Logs

$page.url: http://localhost:5173/page-2 +layout.svelte:7:13
afterNavigate: undefined → http://localhost:5173/page-2 +layout.svelte:24:12
beforeNavigate: http://localhost:5173/page-2 → http://localhost:5173/page-2?preserveThisParam=true +layout.svelte:18:12
$navigating: http://localhost:5173/page-2 → http://localhost:5173/page-2?preserveThisParam=true +layout.svelte:9:12
$page.url: http://localhost:5173/page-2?preserveThisParam=true +layout.svelte:7:13
afterNavigate: http://localhost:5173/page-2 → http://localhost:5173/page-2?preserveThisParam=true +layout.svelte:24:12
beforeNavigate: http://localhost:5173/page-2?preserveThisParam=true → http://localhost:5173/?preserveThisParam=true +layout.svelte:18:12
$navigating: http://localhost:5173/page-2?preserveThisParam=true → http://localhost:5173/?preserveThisParam=true +layout.svelte:9:12
$page.url: http://localhost:5173/?preserveThisParam=true +layout.svelte:7:13
afterNavigate: http://localhost:5173/page-2?preserveThisParam=true → http://localhost:5173/?preserveThisParam=true +layout.svelte:24:12
beforeNavigate: http://localhost:5173/ → http://localhost:5173/page-1 +layout.svelte:18:12
$navigating: http://localhost:5173/ → http://localhost:5173/page-1 +layout.svelte:9:12
$page.url: http://localhost:5173/page-1 +layout.svelte:7:13
afterNavigate: http://localhost:5173/ → http://localhost:5173/page-1 +layout.svelte:24:12

System Info

System:
    OS: macOS 13.4
    CPU: (8) arm64 Apple M1 Pro
    Memory: 88.88 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.12.1/bin/yarn
    npm: 8.19.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
  Browsers:
    Chrome: 114.0.5735.106
    Firefox: 113.0.2
    Safari: 16.5
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
    @sveltejs/kit: ^1.5.0 => 1.20.2 
    svelte: ^3.54.0 => 3.59.1 
    vite: ^4.3.0 => 4.3.9

Severity

serious, but I can work around it

Additional Information

No response

iteratetograceness commented 1 year ago

I'd like to tackle this one!

ghostdevv commented 1 year ago

Go for it!

stuartbritt commented 2 months ago

I've just come across this using the svelte 5 RC. Are there any plans to fix this in Svelte 5?