Skip to content

Instantly share code, notes, and snippets.

@SymphonySimper
Last active October 21, 2024 03:55
Show Gist options
  • Save SymphonySimper/fe67a3218b5f52b8dacc2a8684544d71 to your computer and use it in GitHub Desktop.
Save SymphonySimper/fe67a3218b5f52b8dacc2a8684544d71 to your computer and use it in GitHub Desktop.
Svelte 5 doubts

How to make PageData reactive with $props

Here is what I use in non-rune mode

+page.ts

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

	export let data;

	$: pageNum = data.selected.pageNum;
	// Local state: sets to new option value from server when data changes
	$: selectedSomeOption = data.selected.someOption;

	function changeURL() {
		goto(`/?pageNum=${encodeURIComponent(pageNum)}`);
	}
</script>

<div class="w-screen h-screen flex items-center justify-center flex-col gap-4">
	<div class="text-xl font-bold">
		{selectedSomeOption} ({pageNum})
	</div>

	<div class="flex gap-2 items-center justify-center">
		<button
			class="border border-blue-500 p-2 rounded-lg text-blue-500"
			on:click={() => {
				selectedSomeOption = 'New Option value!';
			}}
		>
			Change Option
		</button>

		<button
			class="bg-blue-500 text-white p-2 rounded-lg"
			on:click={() => {
				pageNum += 5;
				changeURL();
			}}
		>
			+5
		</button>
	</div>
</div>

+page.server.ts

import type { PageServerLoad } from './$types';

export const load: PageServerLoad = ({ url }) => {
	let pageNum = +(url.searchParams.get('pageNum') ?? 0);
	if (pageNum > 10) {
		pageNum = 0;
	}
	return {
		selected: {
			pageNum: pageNum,
			someOption: `hello ${Math.floor(Math.random() * 100)}`
		}
	};
};

This is what I have tried with runes. Here the value is being set for data.selected.someOption but that's not triggering a re-render. The data.selected.pageNum works just fine (But this is also does not trigger a re-render. It just apperas to work because of the goto function call).

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

	let { data } = $props();

	function changeURL() {
		goto(`/runes?pageNum=${encodeURIComponent(data.selected.pageNum)}`);
	}
</script>

<div class="w-screen h-screen flex items-center justify-center flex-col gap-4">
	<h1 class="text-3xl text-red-500 font-bold">Runes</h1>
	<div class="text-xl font-bold">
		{data.selected.someOption} ({data.selected.pageNum})
	</div>

	<div class="flex gap-2 items-center justify-center">
		<button
			class="border border-blue-500 p-2 rounded-lg text-blue-500"
			onclick={() => {
				data.selected.someOption = 'New Option value!';
			}}
		>
			Change Option
		</button>

		<button
			class="bg-blue-500 text-white p-2 rounded-lg"
			onclick={() => {
				data.selected.pageNum += 5;
				changeURL();
			}}
		>
			+5
		</button>
	</div>
</div>

Note: same +page.server.ts

svelte-migrate

After this I looked into what svetle-migrate is doing to resolve this. So it replace reactive label $: with run from svelte/legacy. And this does nothing as they have to be declared with $state()

<script lang="ts">
	import { run } from 'svelte/legacy';

	import { goto } from '$app/navigation';

	interface Props {
		data: any;
	}

	let { data }: Props = $props();

	let pageNum;
	run(() => {
		pageNum = data.selected.pageNum;
	});
	// Local state: sets to new option value from server when data changes
	let selectedSomeOption;
	run(() => {
		selectedSomeOption = data.selected.someOption;
	});

	function changeURL() {
		goto(`/?pageNum=${encodeURIComponent(pageNum)}`);
	}
</script>

<div class="w-screen h-screen flex items-center justify-center flex-col gap-4">
	<div class="text-xl font-bold">
		{selectedSomeOption} ({pageNum})
	</div>

	<div class="flex gap-2 items-center justify-center">
		<button
			class="border border-blue-500 p-2 rounded-lg text-blue-500"
			onclick={() => {
				selectedSomeOption = 'New Option value!';
			}}
		>
			Change Option
		</button>

		<button
			class="bg-blue-500 text-white p-2 rounded-lg"
			onclick={() => {
				pageNum += 5;
				changeURL();
			}}
		>
			+5
		</button>
	</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment