Skip to content
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

reactive statement breaks with object #4426

Closed
pushkine opened this issue Feb 17, 2020 · 6 comments
Closed

reactive statement breaks with object #4426

pushkine opened this issue Feb 17, 2020 · 6 comments

Comments

@pushkine
Copy link
Contributor

https://svelte.dev/repl/c9d2dca597f648eb806ca4876ce04ce7?version=3.18.2

@antony
Copy link
Member

antony commented Feb 18, 2020

There is a bug template for a reason. Your REPL doesn't clearly explain the issue you are having, and as such it is impossible to help you with it.

@antony antony closed this as completed Feb 18, 2020
@pushkine
Copy link
Contributor Author

pushkine commented Feb 19, 2020

I'm sorry @antony, I thought the REPL was clear enough

typing in <input bind:value> triggers the reactive statement $: value = object.property, I do not expect reactive statements whose dependencies did not change to trigger

the REPL also shows that removing the onclick event wherein the reactive statements's dependency is mutated compiles into code where the reactive statement is rightly not triggered on value change

@antony
Copy link
Member

antony commented Feb 19, 2020

You've got both a dynamic property and a declared variable called value. When you type in the input it updates value because you are changing it's value.

let value declares a variable, as does $: value = ...

I'm not sure what you're trying to do here exactly, but I'm surprised that the compiler lets you. Either way the code in the REPL isn't correct, and the results are likely to be unpredictable / nonsensical.

@pushkine
Copy link
Contributor Author

pushkine commented Feb 19, 2020

you are mistaken, svelte only injects declarations to undeclared variables
removing the declaration does not fix the bug

@rixo
Copy link
Contributor

rixo commented Feb 23, 2020

@antony I think @pushkine is right, there seems to be something wrong... even if I'm not entirely sure what the correct behaviour should be.

But the behaviour is not the same when using a raw variable and when using an object property, which I think is unexpected.

Here's a shortened version of the problematic REPL linked above:

<script>
  const object = { property: 'static' }
  object.whatever = 42	
  $: value = object.property
</script>
<input bind:value>

With this, the reactive block is triggered when value changes (that is, when you type in the input).

However, if the object property is replaced by a raw variable, then the reactive block is not triggered when value changes:

<script>
  let property = 'static'
  property = 42 // just to mirror above code, doesn't change a thing
  $: value = property
</script>
<input bind:value>

The discrepancy (as noted in the REPL) disappears when there isn't any assignment to the object (and so, I guess, it is not tracked by Svelte). And so, the following behaves like a raw variable again (i.e. the reactive block is not triggered when value changes):

<script>
  const object = { property: 'static' }
  // object.whatever = 42	
  $: value = object.property
</script>
<input bind:value>

To be honest, I initially thought that the reactive block was due to rerun in the second case, because value is present in the reactive block. But after seing this, I guess that's not the case? Reactive expressions are not triggered by changes to variables that are only written and never read in it, right? I vaguely remember that Svelte has some kind of protection against infinite loop in reactive expressions, I guess this is part of it...

Anyway, I too would expect these 3 code samples to behave exactly the same.

@antony antony reopened this Feb 23, 2020
@pushkine
Copy link
Contributor Author

I suggest taking this conversation to #4448 as the first post is not descriptive enough and the following comments are out of subject

@rixo it works with a primitive because svelte checks internally whether the value has changed, it does work with an object too if you specify that the component uses immutable props. The underlying issue is that svelte wrongly invalidates both references on input, it still works as expected with immutable references because they can be checked for changes before reactive statements are run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants