svelte
svelte copied to clipboard
Input binding wrongly triggers reactivity of a variable used in it's bind path computation
Describe the bug
When we bind an input to a object property, and if we use an expression to compute that property name, binding not only triggers reactivity of containing object, but also other other objects used in it's property-path computation. For example, if we say <input bind:value={form[schema.name]}>
, changing input not only triggers reactivity over form
object, but also on schema
object used in property name computation.
And if we declare to reset form
on schema
change, that will be mis-triggered on value change to above binding, and effectively resets form, and binding itself again.
To Reproduce
Here is REPL. Try to input in field, and we can see reactivity mis-triggering on schema
.
Expected behavior
should not trigger reactivity on other objects used in expression to compute property path.
Severity
Seems serious.
Additional context
Possibly related issues:
#4448 , #4933
I do have the same problem on the last svelte version using inputs from https://github.com/matyunya/smelte. Version 3.24.0 erase input content when blurring the field. Version 3.23.2 works just fine.
I can reproduce this issue with version 3.23.2 as well: https://svelte.dev/repl/4080ea1bee0249fba011f3f25707dbd8?version=3.23.2
Hello, I have the same issue on latest version 3.25 as well : https://svelte.dev/repl/ea825f47db4e44b1b29864ebe2f61e34?version=3.25.1
When using a simple string it works as expected but using an object will trigger reactivity on the object and not only its property.
Here is another example that triggers this behaviour: https://svelte.dev/repl/257464acef204b68a2c2ae77d56db5f5?version=3.51.0
This comes down to $:
standing for two things and it's not easy to distinguish:
- side effects that happen in reaction to something
- derived state that keeps values in sync
Svelte 5 fixes this by separating these into two distinct runes, $effect
and $derived
. That way it's much clearer what's going on and such edge cases are avoided entirely.
In this case, you would have a $state
variable and either update that through the binding of from an $effect
, resulting in the desired behavior.