Svelte 5 führt neue Runen-API ein

Seite 2: $derived-Rune

Inhaltsverzeichnis

Zum Zeitpunkt der Veröffentlichung geht das Svelte-Entwicklerteam der Überlegung nach, Runes per Default nur in .svelte- und .svelte.js/ts-Dateien zu erlauben, damit für Developer und Compiler sofort ersichtlich ist, in welchen Dateien Runes enthalten sein können. Wahrscheinlich wird das jedoch konfigurierbar sein.

Neben $state gibt es noch weitere Runes. Die erste davon ist $derived, die – wie der Name vermuten lässt – abgeleiteten Zustand darstellt:

let count = $state(0);
const double = $derived(count * 2);

$derived ersetzt die Reactive Statements, die vorher so aussahen:

let count = 0;
$: double = count * 2;

Neben der geänderten Syntax hat $derived einen entscheidenden Vorteil bei der Verwendung: Wann immer der Wert ausgelesen wird, ist er aktuell. $: double = count * 2 wurde immer nur direkt vor dem Rendern des UI auf den neuen Wert aktualisiert, was in der Vergangenheit schon oft zu unangenehmen Überraschungen bei Svelte-Nutzerinnen und -Nutzern führte.

Reaktive Statements ließen sich außerdem für Seiteneffekte nutzen:

let count = 0;
$: console.log(`The count is now ${count}`);

Die werden durch die $effect-Rune ersetzt:

let count = $state(0);
$effect(() => console.log(`The count is now ${count}`));

Auch hier gilt: Auf den ersten Blick mag das für erfahrene Svelte-Nutzerinnen und -Nutzer wie ein Rückschritt wirken, doch ist es wesentlich leserlicher – Entwicklerinnen und Entwickler verbringen viel mehr Zeit mit dem Lesen als dem Schreiben von Code – und bietet zusätzliche Vorteile. So kann man bei Bedarf eine Funktion von $effect zurückgeben, die immer dann aufgerufen wird, bevor $effect zum Einsatz kommt oder wenn die Komponente zerstört wird. Der folgende Code wäre in Svelte 4 deutlich aufwendiger zu schreiben:

let count = $state(0);
$effect(() => {
	let seconds = 0;
	const interval = setInterval(
		() => console.log(`The count is ${count} since ${++seconds} seconds`),
		1000
	);
	return () => clearInterval(interval);
});

$effect wird mindestens einmal ausgeführt, und danach immer dann, wenn sich eine seiner Abhängigkeiten ($state oder $derived, der innerhalb des Effekts gelesen wird) geändert hat. Der Effekt wird nach dem Neurendern des User Interface (UI) ausgeführt. Wer stattdessen direkt vor dem Rendern einen Effekt ausführen will, nutzt $effect.pre – die API ist identisch zu $effect, nur das Timing ist anders.

Zu guter Letzt gibt es noch die $props()-Rune, die zur Definition der Properties einer Komponente zum Einsatz kommt. Sie ersetzt die bisherigen export let-Definitionen.

<script>
	let { surname, lastname } = $props();
	// vorher:
	// export let surname;
	// export let lastname;
</script>

<p>Hello {surname} {lastname}</p>

Insgesamt erfordern Runes vorab ein kleines bisschen mehr Denkarbeit ("ist das hier Zustand? Dann muss ich die $state Rune nutzen") und minimal mehr Schreibarbeit. Dafür ist der Code leserlicher, wartbarer, leichter zu refaktorieren, und kompliziertere Patterns sind durch die universelle Reaktivität einfacher möglich. Svelte wird zudem noch einfacher zu erlernen, da sich alles, was besonders im Script-Teil einer Komponente ist, durch Runen ausdrücken lässt.