question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

$: reactive shortcut is not current with multiple sync updates to a writeable store

See original GitHub issue

Describe the bug

$: does not reliably fire with a writeable store, while store.subscribe does.

It seems like all initial writeable store updates within the same tick are gathered, with only the last, most recent one firing for the $: reactive handler, usually. However, it seems like it can be possible for the $: handler to fire pre-maturely, when there are still other state updates to happen within the same tick, which wind up going un-reported.

See repro link below.

Reproduction

https://svelte.dev/repl/57dbee8266d840d09611daebee226b91?version=3.42.5

I get the following in the dev console. Note that the {loading: "true"} update is not reported from the $: handler, with the XXX, until the NEXT update happens. This results in the wrong state being reported, initially.

image

Note that moving the call to sync up, fixes this. It seems like Svelte’s analysis of the code is missing an odd edge case.

https://svelte.dev/repl/e88c70d6fd224b0d84656f83afd7e63c?version=3.42.5

Logs

N/A

System Info

REPL

Severity

blocking an upgrade

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:110 (94 by maintainers)

github_iconTop GitHub Comments

9reactions
dummdidummcommented, Sep 21, 2021

@Rich-Harris @benmccann @arackaf Including the new and more fleshed out example here rather than on the other ticket to keep a single thread of discussion going. Please see this REPL I included instructions and some hopefully helpful comments.

To me this REPL still feels kind of backwards. I would’ve written it differently probably, avoiding the need for a rerun.

Still, I think having a possibility to opt in (not out) of reruns would be a good addition to the framework. We can’t expect people to write code like we want them to at all times, and when they realize they coded themselves into a situation where they need that rerun, it should be available.

Regarding syntax: I don’t like $: { deps } { doStuff() }. Reasons:

  1. To me it reads like two distinct things because they are both closed in itself. To me, this doesn’t read like “the first one defines behavior of the second”
  2. “Prettier will print this in a less “is connected”-way, but that shouln’t be a problem because we can update prettier-plugin-svelte” -> not true, it would be a huge undertaking to change this print. prettier-plugin-svelte delegates formatting of script tags to the core Prettier formatters, so we either need to fork that (impossible to maintain), or inspect the resulting docs array (highly discouraged by the Prettier team, could break frequently if inner doc structure changes). The “Prettier prints it in a less connected way” also is a hint towards point 1.
  3. As @Conduitry noted, this could produce syntactically invalid code if people use break statements, which I think was one of Svelte’s non-goals and which we should keep from doing as long as possible

I actually really like @arxpoetica’s solution to make this a inner label, although I would maybe name it to make it more clear:

$: {
  $rerunOn: [foo, bar];
  // actual logic
}

This would also make it possible to add more labels for more fine-tuned behavior later on. For example this could mean “these are my deps, but don’t rerun when one of them change while calculating this”:

$: {
  $deps: [foo, bar];
  // actual logic
}

Whereas $rerunOn means “rerun this block when any of the listed variables are invalidated, even if this block already ran”. There could be situations where you want both $deps and $rerunOn to be defined, and that would be possible now.

Regardless of how this discussion turns out, we really should have an “advanced docs” section going into more details for things like this and for providing best practices.

8reactions
isaacHagoelcommented, Sep 26, 2021

I would add that I was curious how other frameworks would deal with this test case. First I tried Solid because it has a reputation for having one of the most, well, solid reactive systems (that self infers the dependencies like Svelte does). Seem to be behaving as expected with no surprises and very consistently. See here. It is not sensitive to the order of the effects and always logs 6 times.

React also resolves correctly although it has some sensitivity (number of operations) to the order of the effects. See here

How can we get svelte (which, generally speaking, has far superior DX relative to both of the above) to the same level of predictability and robustness?

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to get store value from another store? - svelte
Use get(store) to access a stores value. Example: import {get, writable} from 'svelte/store' const myStore = writable(41) const value ...
Read more >
Stores / Writable stores • Svelte Tutorial
It's a writable store, which means it has set and update methods in addition to subscribe . Now go to the Incrementer.svelte tab...
Read more >
@square/svelte-store - NPM Package Overview - Socket
Start using Socket to analyze @square/svelte-store and its 2 dependencies to secure your app from supply chain attacks.
Read more >
Working with Svelte stores - Learn web development | MDN
There we assign a new value to a local variable, and thanks to Svelte reactivity all our markup and reactive dependencies are updated...
Read more >
Managing state in Svelte - DEV Community ‍ ‍
Joshua Nussbaum. Posted on Feb 26, 2020 • Updated on Mar 2, 2020 ... Stores. Not all state belongs in the component tree....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found