question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

page props are re-set whenever the `session` store is updated, and the `load` function is re-run the first time

See original GitHub issue

Describe the bug

In the docs, in the section about the load function, it’s stated that:

…if url, session or stuff are used in the function, they will be re-run whenever their value changes… (here)

But this doesn’t seem to be the case. I have the following page in my SvelteKit app: index.svelte:

<script lang="ts" context="module">
    import type { Load } from '@sveltejs/kit';

    export const load: Load = () => {
        console.warn('index load function');
        return {};
    }
</script>

<script lang="ts">
    import { session } from '$app/stores';

    function changeSession() {
        $session.someField = Math.random();
    }
</script>

<pre>{JSON.stringify($session, null, 4)}</pre>

<button on:click={changeSession}>
    Change $session
</button>

If you click on the “Change $session” button, you’ll see the message “index load function” appearing in the console, which obviously means the load function is re-run, even though session isn’t used in the load function. This is inconsistent with the behavior described in the docs.

The strange thing, however, is that from the second time onwards, when the value of the ‘$session’ store changes, the load function is no longer re-run. This is confusing.

The more severe bug, however, which seems to be related to this one, is that every time the $session store changes, the page’s props are apparently re-set, which means reactivity is re-triggered throughout the entire page, potentially causing massive problems.

Consider the following:

<script lang="ts" context="module">
    import type { Load } from '@sveltejs/kit';

    export const load: Load = () => {
        console.warn('index load function');
        return {
            props: {
                userBasicInfo: {
                    id: 2,
                }
            }
        };
    }
</script>

<script lang="ts">
    import { browser } from '$app/env';
    import { session } from '$app/stores';

    export let userBasicInfo;

    function changeSession() {
        $session.someField = Math.random();
    }

    $: console.log('userBasicInfo changed:', userBasicInfo);
</script>

<pre>{JSON.stringify($session, null, 4)}</pre>

<button on:click={changeSession}>
    Change Ssession
</button>

<hr />

{#if browser}
    {#await fetch(`https://reqres.in/api/users/${userBasicInfo.id}`).then(r => r.json())}
        Loading...
    {:then result}
        <pre>{JSON.stringify(result, null, 4)}</pre>
    {/await}
{/if}

In this setup, whenever you click on the “Change $session” button — which is to say whenever you update the $session store — the fetch request in the markup, which uses the userBaicInfo prop, is re-triggered, even though it obviously shouldn’t. And you can see the userBasicInfo changed: ... message in the console which proves that it’s because of the userBasicInfo prop getting re-set.

Reproduction

You can create an empty SvelteKit skeleton project and then copy-paste the two code snippets above into the index.svelte file, and then npm run dev => open your browser and see the behavior for yourself.

Logs

No response

System Info

System:
    OS: Windows 10 10.0.19042
    CPU: (4) x64 Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
    Memory: 1.09 GB / 7.89 GB
  Binaries:
    Node: 14.15.0 - C:\Program Files\nodejs\node.EXE     
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD       
    npm: 6.14.8 - C:\Program Files\nodejs\npm.CMD        
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (97.0.1072.76)
    Internet Explorer: 11.0.19041.1202
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.17
    @sveltejs/kit: next => 1.0.0-next.260
    svelte: ^3.44.0 => 3.46.4

Severity

blocking all usage of SvelteKit

Additional Information

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
DrDanRyancommented, Jun 30, 2022

Needless to say, props being reset whenever $session changes can cause many unexpected problems for users, I’m not sure why it happens but I think it should be considered a bug.

Agreed, this has been driving me nuts for days until I finally became sure that it was a bug with Sveltekit and not me just being stupid. To add to the strangeness, you can even change the page props and then call a setTimeout for a large amount of time to set the $session store value and after the $session store value gets set the page props will revert to their previous value. How is this even possible!?

0reactions
DrDanRyancommented, Jun 30, 2022

If its any help, this is my minimal reproduction of the bug you can see that the props (user in this case) get reset when the $session assignment is made 2 seconds after the post call is resolved.

// index.svelte
<script>
	import { session } from '$app/stores';
	export let user;

	async function submit() {
		const response = await fetch('/', {
			method: 'POST',
			headers: { accept: 'application/json' }
		});
		const body = await response.json();
		user = body.user;
		setTimeout(() => {
			$session.message = body.message;
		}, 2000);
	}
</script>

<div>{JSON.stringify($session)}</div>
<p>Hello {user}!</p>
<button on:click={submit}>Submit</button>
// index.js
export async function get() {
	return {
		body: {
			user: 'Bob'
		}
	};
}

export async function post() {
	return {
		body: {
			user: 'Tom',
			message: 'I come from the post call!'
		}
	};
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

What's the point of rerunning the `load` function on `session ...
When I do a silent refresh I reset the session, but this causes a rerun of the load function now. The problem with...
Read more >
React prop shows as empty on first load after change
I have an application which follows these steps: User adds a new currency to account; HTTP request sent to server; Then this.props.
Read more >
React Hooks cheat sheet: Best practices with examples
Updating a state variable is as simple as invoking the updater function returned by the useState invocation: const [stateValue, updaterFn] = ...
Read more >
Dynamic behavior in Svelte: working with variables and props
In our app, the todos array value is updated directly every time a to-do is toggled or deleted, and so Svelte will update...
Read more >
Loading data • Docs • SvelteKit
Thanks to the generated $types module, we get full type safety. A load function in a +page.js file runs both on the server...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found