-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different reactivity triggering of props (automatic derived inserted sometimes) #15406
Comments
We do this when there's a function call involved...this is because you don't want the function to be called everytime (which would happen if we didn't wrap it in a derived)...however the bug feels the fact that it's rerunning even if name didn't actually changed. I suppose is because what is changing it's actually the whole object which triggers the effect. Mmm i don't know how i feel about this. |
I see, but in this case, I'd actually want the function to run each time.. If I didn't, I'd use an explicit derived or const. Otherwise, I'd expect that a reassignment of In other words, I like the mental concept of "props are just getters, derived/const triggers differently". |
The point is that the props you are passing is just the value and with fine grained reactivity it the value doesn't change it shouldn't rerun...that's why I'm surprised it does and I wonder if we should actually fix this in some way 🤔 |
Hmm.. So you mean that all props should be automatically derived? Makes sense, although it complicates the above use case a little bit. Sometimes you simply need to rerun things even when the value didn't change.. (but it's still doable if you pass the whole object as a prop) On the other hand, the state of the art can be surprising, because it behaves differently for:
and
(we have already stumbled upon an issue with this in our codebase but then we thought that's a feature not a bug) |
If I'm right though, you'd still get the "nonderived" behaviour when doing an effect: $effect(() => {
some.nested.foo;
}); I guess that should/would trigger no matter if foo actually changed its value or not.. |
Can I ask you what's the use case here? |
I guess it's generally when working with inputs. The reason is that input has it's inner state and sometimes you need to overwrite what the user typed in. But when the overwritten value (the prop) hasn't changed itself, the overwriting doesn't happen. I can prepare a REPL to illustrate it better :) |
If you can that would be great...but i would say don't do this in effects |
So here it is: https://svelte.dev/playground/420aa35591fe41aa91eb20e81d24973d?version=5.20.5 This one is a bit different than what I tried to describe. And I must say I'm a bit confused now why it does not work as I expected :D. The case here is that you have an input that automatically appends a unit ("mm") if the user puts a unitless number in it. So if you put "100" then it updates the state and the input to "100 mm". The issue is when you have "200 mm" in the input field and then you just delete the units and then press enter. The value itself ("200 mm") didn't change, but now the state is different from what the user sees in the input (there is still only "200" in the input field). |
I think this is a different issue but there's not much svelte can do here...you can change your strategy and do something like this by setting the value within |
Ok, I assume there might be another issue there. Thanks for the updated example, although it feels more like a hotfix than an actual solution. By changing the strategy you mean like don't even automatically change the value of the input? Or some other way to accomplish the same? Getting back to the previously discussed...
Well I don't know what fine-grained reactivity really means exactly.. I feel like it is more connected to the deep/proxied |
Btw the problem specifically with inputs is that we check if the value is the same and don't update the input (if i'm not mistaken) |
Yea might be, I quickly skimmed through the source code and there is a check |
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:
and other times it is used directly in the getter:
<Component name={state.name}/>
which results in:
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 REPL
Severity
annoyance
The text was updated successfully, but these errors were encountered: