How to update the page and query parameters in SvelteKit?
Asked Answered
A

6

20

I have a page with a search field. If accessed with a query parameter (e.g. ?word=cat) the page should load with results present and the search field filled. If a search is done the results and the query parameters (browser history) should update.

The only way I found to update query parameters is goto, so my attempt is:

<script context="module">
  export async function load({ page, fetch }) {
    const response = await fetch(`/data.json?${page.query.toString()}`)
    if (response.ok) {
      return {
        props: {
          word: page.query.get('word'),
          body: await response.json()
        }
      }
    }
  }
</script>

<script>
  import { goto } from '$app/navigation'
  import { page } from '$app/stores'

  export let word
  export let body

  function search() {
    $page.query.set('word', word)
    goto(`?${$page.query.toString()}`)
  }
</script>

<main>
  <form on:submit|preventDefault={search}>
    <input bind:value={word}>
  </form>
  <!-- ... -->
</main>

This works but sometimes gets stuck just updating the query parameters and nothing else. For some reason load isn't being called in those cases. I can get it to work reliably by adding await invalidate for the URL before the goto, but now load is always called twice and the search field flips back to the old value shortly.

I just started with Svelte/SvelteKit, so my approach is probably just wrong. Thanks for any help.

Alliterative answered 17/10, 2021 at 16:9 Comment(2)
try removing the $page.query.set line and simple have goto that should be enoughGuilt
Thanks, I replaced it with a separate URLSearchParams and it works.Alliterative
L
25

I had similar issue triggering load function and I solved it by creating new instance of the URLSearchParams and navigating to these new params.

let query = new URLSearchParams($page.url.searchParams.toString());
    
query.set('word', word);
        
goto(`?${query.toString()}`);
Littman answered 4/11, 2021 at 9:40 Comment(2)
You don't actually have a create a new URLSearchParams object passing the page.query. the $page.url.searchParams; already returns a urlSearchParams object so you can just assign that to a variable: const urlSearchParams = $page.url.searchParams; Billon
@Nicholas Mordecai I respectfully disagree. See Anatole Lucet's comment.Codicil
B
25

$page.query is no longer available since it was replaced by $page.url (in @sveltejs/[email protected]).

Now, it is done like this:

$page.url.searchParams.set('word',word); 
goto(`?${$page.url.searchParams.toString()}`);

$page and goto() you can get from:

import { goto } from "$app/navigation";
import { page } from "$app/stores"; 
Braddock answered 12/3, 2022 at 14:52 Comment(1)
Actually, this will mutate page's internal URLSearchParams which might cause some issues when working with reactive statements. A better way would be to create and mutate a new URLSearchParams from $page.url.searchParams, and then use it in the goto (goto(newSearchParams)).Daugavpils
C
4

You can pass in a URL type in goto function.

const newUrl = new URL($page.url);
newUrl?.searchParams?.set('hello', 'world');
goto(newUrl);

https://kit.svelte.dev/docs/modules#$app-stores-page https://kit.svelte.dev/docs/modules#$app-navigation-goto

Cryohydrate answered 25/7, 2022 at 6:41 Comment(0)
P
1

An even shorter approach:

$page.query.set('word',word); 
goto(`?${$page.query.toString()}`);
Phasia answered 11/11, 2021 at 12:51 Comment(1)
github.com/sveltejs/kit/issues/2785Phasia
B
0

To prevent an extra navigation and reload:

$page.query.set('word',word); 
history.replaceState(history.state, '', $page.url);
Bayles answered 20/8, 2023 at 17:8 Comment(0)
H
0

Try this snippet on your page.

Subscribe to query parameter changes with a reactive statement if needed:

I think this is a better approach than navigating to a different page with goto()

http://localhost:5173?tag=travel

<script lang="ts">
  import { page } from "$app/stores";
  // Reactive statement to log a specific query parameter
  $: console.log($page.url.searchParams.get('tag'));
</script>
Historied answered 30/6 at 7:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.