The below code is working as it should, I'm just trying to gain a better understanding of why.
How is the getCurrentElement
method of TestState
reactive without the use of $derived()
? Are store methods that make use of state reactive by default?
Im using svelte@5.0.0-next.217
test-store.svelte.ts
import { getContext, setContext } from 'svelte';
class TestState {
elements = [
{
id: 'hghxt',
name: 'Give',
},
{
id: 'vhtl9',
name: 'Connection',
},
{
id: '5n0t0',
name: 'Take notice',
},
{
id: 'xlfba',
name: 'Keep learning',
},
{
id: '1f3z2',
name: 'Be active',
},
];
#currentElementId = $state<string>();
getCurrentElement() {
return this.elements.find(element => element.id === this.#currentElementId);
}
setCurrentElement(id: string) {
if (!this.elements.some(element => element.id === id)) return;
this.#currentElementId = id;
}
}
const TEST_STORE_KEY = Symbol('TEST_STORE');
export function setTestState() {
return setContext(TEST_STORE_KEY, new TestState());
}
export function getTestState() {
return getContext<ReturnType<typeof setTestState>>(TEST_STORE_KEY);
}
TestComponent.svelte
<script lang="ts">
import { getTestState } from '$lib/stores/test-store.svelte';
// initialised at +page.svelte
const testState = getTestState();
</script>
{#each testState.elements as { name, id }}
<button
class:bg-yellow={testState.getCurrentElement()?.id === id}
onclick={() => testState.setCurrentElement(id)}>
{name}
</button>
{/each}
In your "HTML code" you call testState.getCurrentElement()
. When you do that, Svelte will notice which reactive variables that call is dependent on. In getCurrentElement()
you access this.#currentElementId
, so that way Svelte knows that this part of the "HTML code" needs to be re-rendered/updated when this.#currentElementId
is assigned a new value.
You only need to use $derived()
when you want to automatically compute a new value as soon as a reactive variable changes value, and that's not the case for you here, so here I don't see any point in using $derived()
here.
@JackTempleman, maybe we call things differently, but there is no such thing as a reactive function, at least not in my vocabulary. We only have reactive variables/expressions, which can be created using some runes, like $state()
. If one of your function uses a reactive variable/expression, then that function itself is not reactive; it's just a function that uses reactive variables/expressions. Only creating such a function will not cause anything to recompute on its own. But if you call/use such a function at some places where Svelte tracks reactivity (like in the HTML code in a component or in some runes), then Svelte will become aware of the reactive variables/expression the function uses, and Svelte will call the function again in the future when those reactive variables/expressions changes value.