-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Explicit dependencies for reactive statements + Syntax proposal or Docs update #5615
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
Comments
You can already sort-of do this: |
isn't valid JS syntax, and so isn't something we can use. As Kev mentions, you can already do this with a different syntax. Having a more in-depth guide/cookbook-type section on the site that discusses more details about how the reactivity works and how to achieve various results is something that's planned, and there's at least one issue for it somewhere. |
As @kevmodrome mentioned there are a series of equivalent syntaxes to the one I presented in the example above that works in some cases, but that's not the point of the issue: using the comma operator or an array + && does not solve the problem of nested properties because the reactive statement gets triggered if any of the values an object contains changes, even if the one the reactive statement is "watching" stays the same, thus I think that the only way to implement this behavior is to create a specific syntax. That's the main reason, right now there is no way to make a reactive statement on a single object property without having to manually check if the property actually changed, which is a bit counter-intuitive. About the "invalid JS syntax", it's not really a compelling argument considering that Svelte is a compiler and that even if $: is valid JS syntax it has completely been repurposed in a way that makes it inconsistent with what any JS engine would interpret. Same applies for the autosubscription, $ before a variable name shouldn't modify the behavior of that variable but yield "$something is not defined" or even "assignment to undeclared variable $something" considering that $ is a valid character in a variable name. |
Here is a REPL demonstrating what I'm referring to: |
You can get around that by passing through an intermediate value, in a sense destructuring your object and only 'listening' to changes to specific props $: prop2 = obj.prop2
$: if (prop2) {
counter++;
} |
@stephane-vanraes only if prop2 is a primitive value, otherwise it still gets triggered, because the invalidation process that triggers reactive statements treats objects and primitive types differently. As before, a specific syntax that override the automatic dependency graph would solve this, but right now there are only workarounds. The one you suggest can work with nested properties only by walking down all the hierarchy until the one you want to watch is reached (assuming one needs to listen to that primitive property and not a whole nested object). |
further to reduce the naming problem:
|
further, maybe
|
Why not just use the $ label technique: $name: {
} This is a non-breaking change; the compiler would not have to be changed much, and the implementation could be hidden behind a writable(). Watching multiple variables would imply multiple statements, but the syntax is clean: let one, two, three;
$one: ...;
$two: ...;
$three: ...; |
Typescript still cry for this syntax. |
Is your feature request related to a problem? Please describe.
This feature is related to the ambiguity of reactive statement inference methods that, by abstracting the process of determining the dependencies, can cause unintended behavior (more in the examples below). This feature is an addition to the syntax that enables users to explicitly signal which variables should trigger a reactive statement, without changing the current behavior of standard reactive statements.
Describe the solution you'd like
As per the example below, a possible solution can be the idiom:
With this syntax simple values can be watched by the reactive statement, and, because an array always evaluates to true, any time one of the variables gets reassigned, it will be triggered independently of the variables read in the function code which won't affect the dependency graph computed by Svelte.
BUT if any of the watched variables is the property of an object, the statement gets wrongly triggered even if that particular property wasn't changed. Because changing the way the dependency graph works would be a major breaking change and probably confuse a lot of developers that are already familiar with the current behavior, I came up with another idea: we could create a specific syntax that explicitly states the dependencies of a reactive block, thus letting the compiler skip the automatic construction of the dependency graph for this kind of statements.
I can imagine something like the following:
The square brackets can be adopted because they won't create ambiguity with jQuery-like function calls and also for symmetry with the cited idiom.
Describe alternatives you've considered
It's often the case that in a reactive statement a variable is read or written to or it is assumed it will be written to because of a nested structure, thus triggering related statements. A classic example of this behavior has been brought up numerous times in this repository with something like this:
The example above results in a readonly input field, because
obj
is invalidated any timeinputValue
is. There are some ways to work around this problem, for example wrapping the reactive statement code in a function. Doing so, the example above becomes:This fixes the reactivity problem by explicitly stating that the
reactiveCode
function should only be called whenobj
is changed.Another way to explicitly state dependencies for a reactive block I've also found is this idiom:
REPL: https://svelte.dev/repl/de48158c145a437e9cdf7f9896349354?version=3.29.4
In this example the reactive code does not depend on
flag
but the intended behavior is that whenever theflag
variable changes, the border color must change. Moreover the reactive code is wrapped in a function so that even if there were other variables read in that code, they wouldn't affect the dependency graph.Even if this syntax proposal gets rejected, I think that the idiom that already works should be added to the Svelte Docs and Tutorial so that anyone can take advantage of this behavior without having to figure out how reactivity is currently implemented for different types.
How important is this feature to you?
The new syntax per se is a really nice-to-have feature because it would solve different kinds of problems with very little verbosity when compared to the idiom. If instead the syntax gets rejected, I think it's really important to clearly state in the Tutorial and Docs how reactivity works when function calls are involved and present this example as a solution for use cases when a user wants to control which variables the code should react to.
Additional context
Related issues:
The text was updated successfully, but these errors were encountered: