-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Describe the problem
Right now we have {@const ...}
, which is a) weird, b) inconsistent with $derived(...)
, and c) limiting.
Describe the proposed solution
Instead of this...
{#each boxes as box}
{@const area = box.width * box.height}
{box.width} * {box.height} = {area}
{/each}
...we could do this:
{#each boxes as box}
{let area = $derived(box.width * box.height)}
{box.width} * {box.height} = {area}
{/each}
Or if you want it to be read-only, use const
instead. You get the idea.
This would also solve a limitation that people periodically encounter — the fact that you can't create local state. This is particularly irksome if a snippet needs to do something stateful, since you now need to convert it to a component (including carefully moving over any CSS that it uses):
{#snippet counter()}
{let count = $state(0)}
<button onclick={() => count += 1}>
clicks: {count}
</button>
{snippet}
{@render counter()}
{@render counter()}
{@render counter()}
Naturally, $state.raw
and $derived.by
would also be supported, as would normal non-state declarations. We could also allow declarations with multiple declarators:
{let a = 1, b = 2, c = 3}
Migrating existing uses of {@const ...}
in runes-mode components would be trivial...
-{@const x = y}
+{const x = $derived(y)}
...and we could deprecate it at the same time.
This is more powerful, looks nicer, is one less bit of weird non-JavaScript syntax, and is something that would have come in handy a number of times recently.
Scoping would work the same as it does in snippets, i.e. bounded by the parent item (whether that's an element, block or whatever). So this would be possible...
<div>
{let a = 1}
{a}
</div>
<div>
{let a = 1}
{a}
</div>
...but this would be an error because the declaration is duplicated in the same scope:
<div>
{let a = 1}
{a}
{let a = 1}
{a}
</div>
Declarations should precede usage. We probably don't want to allow var
since it would be confusing to have different scoping rules, and different scoping rules are the only thing that distinguishes var
from let
.
We probably do want using
, at least eventually (see #16192).
Importance
nice to have