Skip to content

Runes: Determining what is reactive #9258

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

Closed
WaltzingPenguin opened this issue Sep 25, 2023 · 7 comments
Closed

Runes: Determining what is reactive #9258

WaltzingPenguin opened this issue Sep 25, 2023 · 7 comments
Labels

Comments

@WaltzingPenguin
Copy link

WaltzingPenguin commented Sep 25, 2023

Describe the problem

Consider the component

<script>
import { get_cart } from '$data/cart'
let cart = get_cart()
let total = new Intl.NumberFormat(undefined, { style: 'currency' }).format(cart.total)
</script>

<p>Total: {total}</p>

Is cart reactive? Does it update based on other things or is it grabbed one time? With Svelte 4, this is easy: getCart either returned a store or it is not reactive.

With Svelte 5, the only way to determine this is to open up the definition of getCart and see if $state is used there. On any large project, the definition of getCart probably will call shared helper/utility functions, so you'll have to check those too. Bonus points if it returned something created from inside of node_modules.

Describe the proposed solution

Explicit opt in to reactivitiy or a type used to denote the result of runes. I should understand how this file behaves by looking at just this one file, in isolation.

Alternatives considered

  • Strict naming conventions: Just let everyone I work with know to suffix functions with _state
  • Assume everything is reactive, fix the bugs as they appear

Importance

would make my life easier

@hanszoons
Copy link
Contributor

Would be nice if the vscode extension could somehow help with this, similar to this effort: https://github.com/halfdanj/svelte-reactions

@Gin-Quin
Copy link

An IDE extension would be nice (displaying all 'side-effects' of a variable on hover would be pure gold). It's possible, but quite heavy since the language server must parse the whole codebase.

Other solutions that come to my mind:

  • Using a $ prefix for all reactive variables. I like and dislike this solution at the same time. A sugar syntax like <Component {$value} /> that would convert to <Component value={$value} /> would be necessary.
  • Using a Reactive type that appears when you hover a value. For example: Reactive<number> - which works similarly to a number. Don't know if Typescript permits it.

@WaltzingPenguin
Copy link
Author

IDE solutions are nice. Being able to accurately assess code while looking at a PR in GitHub is better. That requires a different language design than what is currently proposed.

If the above example for Svelte 4, either I would know it was a store because of the $ prefix, svelte-check would catch it as an error because Readable<number> is invalid to pass to .format, or I would request a change to the PR because total shouldn't be calculated exactly once.

@7nik
Copy link
Contributor

7nik commented Sep 30, 2023

Correct me if I get the runes wrong after playing with them a bit, but you can use runes only to define variables and at passing them wherever the reactivity gets lost. So get_cart() simply cannot return a reactive value.

However, if get_cart uses runes internally, $derived and $effect can catch them.

@WaltzingPenguin
Copy link
Author

Correct me if I get the runes wrong after playing with them a bit, but you can use runes only to define variables and at passing them wherever the reactivity gets lost. So get_cart() simply cannot return a reactive value.

Technically it is cart.total that Svelte is potentially monitoring while cart remains a pointer to the same object. From a practical perspective, I don't see the point in making that distinction.

@adminy
Copy link

adminy commented Oct 9, 2023

That last point you considered is interesting. Because if its possible then no special syntax is needed, since everything is reactive.

@dummdidumm
Copy link
Member

The example isn't reactive anyway, since total isn't reactive. In general, while this may require some rethinking, in general you should write the code declaratively assuming that the things that semantically make sense to rerun, do so. You could use naming conventions to make it a bit easier to see, but I assume that you'll have most things reactive anyway, so it's kind of unnecessary. As for analysis, we now $inspect which helps you see which things triggered something, and we'll likely invest into dev tools later on so that you can at runtime get a reactivity dependency graph of a specific thing.
As for explicit dependencies, this is tracked in #9248, therefore closing.

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants