Scott
Scott

Reputation: 312

SvelteKit page data doesn't always update when opening new page in the same dynamic route

I have a route structure /items/[category]. When the user is browsing /items/category1 and then tries to go to a another page in the same route (eg. /items/category2) the page data usually updates to show category2 items, but not always. Sometimes the URL updates in the browser but the page data still shows items from the previous URL.

My +page.server.js for /items/[category] looks like:

import { getItems } from '$lib/services/ItemService';
export const csr = false;
export const load = ({ locals, params }) => {
    return {
        items: getItems(locals, `category = "${params.itemCategory}"`)
    };
};

And my +page.svelte is:

<script>
   import { ItemCard } from '$lib/components';
   export let data
   let items = data.items
</script>
...
<div class="grid grid-cols-1 md:grid-cols-3 px-4 gap-6">   
   {#each items as item}
      <ItemCard {item}/>
   {/each}
</div>

The getItems() function retrieves JSON data from pocketbase and is working correctly.

I read that adding the export const csr = false; to the +page.server.js should solve the problem, but it appears that the page still isn't always re-loading data from the server when swapping between routes.

Upvotes: 15

Views: 7064

Answers (4)

brunnerh
brunnerh

Reputation: 184526

You change local state non-reactively:

let items = data.items

If data is updated by the router, items will not.

Making it reactive might fix the issue:

$: items = data.items              // Svelte 3/4
const items = $derived(data.items) // Svelte 5 runes

You can also destructure props reactively, which requires additional parentheses for labeled statements:

$: ({ items } = data)            // Svelte 3/4
const { items } = $derived(data) // Svelte 5 runes

SvelteKit docs on this issue.

Upvotes: 32

Evilgore
Evilgore

Reputation: 31

Change

let categoryUrl = $page.params.category;

to

$: categoryUrl = $page.params.category;

Upvotes: 3

Cornel Selescu
Cornel Selescu

Reputation: 1

The 'params' attribute is not reactive if you navigate from a similar route (e.g. /items/category2 -> /items/category3). What worked for me for a similar issue was:

import { navigating } from '$app/stores';
let categoryUrl = $page.params.category;
$: {
    categoryUrl = typeof window !== 'undefined' ?  window.location.href.split('/').pop() : $page.params.category;
}
$: if($navigating) {
    let newUrl = typeof window !== 'undefined' ?  window.location.href.split('/').pop() : $page.params.category;
    if(categoryUrl !== newUrl) { 
        .....
    }
}

Upvotes: 0

vihv
vihv

Reputation: 1

This problem has been bugging me for days, and I finally found that the easiest solution is to use window.location.href.

Write your code like this:

<button on:click={() => {
        window.location.href = `/path/${id}`;
      }}>
Go
</button>

Upvotes: -2

Related Questions