-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
I wonder why sometimes a prop getter is wrapped in $derived, such as:
<Component name={state.name.toString()}/>
which results in the following compiled output:
const expression = $.derived(() => $.get(state).name.toString());
Component(node, {
get name() {
return $.get(expression);
}
});and other times it is used directly in the getter:
<Component name={state.name}/>
which results in:
Component(node, {
get name() {
return $.get(state).name;
}
});This behavior seems to be present in Svelte since v5.0. The specific issue I'm having is that this has consequences for reactivity triggering inside the child components. The minimal reproduction is in the REPL.
I assume there is some reason to do this. However, this feels inconsistent (magical) to me. In our codebase, we sometimes want to rely on the "not derived" behavior, i.e. update things even when the content is the same.
An example use case where this actually matters would be having an input field that triggers some on_change when a user inputs something. But in some logic above the resulting value is computed/overwritten to be the same as had been before (thus it should overwrite back what user has typed in). By wrapping the prop in $derived, the signal doesn't update the prop value, so the user's input stays in the input field.
Reproduction
https://svelte.dev/playground/0e8e303022c24b609f4c13b58ef2df9d?version=5.20.5
Remove .toString() on line 7 in App.svelte and now the compiled output doesn't use $derived.
Logs
System Info
reproducible in REPLSeverity
annoyance