-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Svelte 5: Introduce $derived.with
rune
#9968
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
As the person who sparked the Discord discussion with my blog post, I'd like to second this proposal. Having the option to use a callback to
I appreciate Svelte's focus on writing less code and hope it will apply here too. |
Seconded, though I prefer the overload approach, adding an extra overload that accepts a function: let foo = $derived(() => {
// do calculations and return
}); While preserving the current signature as the other overload: let bar = $derived(foo * 2); But if overloads aren't feasible, |
I worry overloading For example in this case: function getTotal() {
const discountAmount = cartTotal * promoDiscount;
const taxedAmount = (cartTotal - discountAmount) * taxRate;
return cartTotal - discountAmount + taxedAmount;
}
const total = $derived(getTotal); The way Also need to consider that it would be a breaking change to alter how |
I think overloading Svelte is all about writing less code. Let’s not have a separate function or an IIFE or |
Overloading is not the best idea. What if I want to return a function from derived? Now I need to return a function from within a function. |
Okay, the reasons against it being an overload sound compelling. |
Personally, I still think my original proposal of The Svelte 5 literature constantly states that the reason for their changes are to reduce the learning curve, so why go against that when it comes to Current const countDoubled = $derived((() => {
return width * height
})()) Function argument proposal for const countDoubled = $derived(() => {
return width * height
}) |
This is definitely a necessary feature. We have a ton of derived stores that compute complex conditions. Without that proposal we will get a problems while migration |
Why is it necessary? It's just a syntax change, you can do what's proposed with a different syntax (IIFEs). |
It can be done with IIFEs, but I’ll restate my post from earlier in this thread and say IIFEs are an awkward, verbose way to code. They go against the whole point of Svelte, to write less code. |
I'm not against the change, but saying it is necessary is a stretch. That's all I'm getting at 🙂 |
I think allowing both callback and expression syntax would be best. In my own experience, derived signals that produce functions are very rare, so I think it's acceptable to force developers to add another indirection for this rare case: // expression syntax for simple things
let area = $derived(width * height)
// callback syntax for long-winded things
let complicatedArea = $derived(() => {
let taylorFactors = [1, 2, 3]
let widthPercent = a^2 + b^2
let width = Mat(taylorFactors).T * widthPercent
return width * height
})
// nested callback syntax for returning functions from derived blocks
let logAreaFn = $derived(() => {
let area = width * height
return () => console.log(area)
}) when the compiler sees a function as the expression within There are many different signal implementations currently in the wild, so far every one that I have seen uses the callback syntax for derived signals. In not allowing this, Svelte would break with the majority of the web ecosystem, which also makes it more confusing for developers coming from other frameworks. There has to be a strong reason to that, and I don't think we have one here. |
This is definitely allowed in vanilla JS. Nothing wrong here. You evaluate an expression and pass it to That you don't have the overhead of thinking "how does the reactive variable get updated then" (like in react or vue) is a good thing and the power of having a preprocessor like svelte does. |
Wrong, it’s undoubtedly not allowed in Vanilla JS. |
@D-Marc1 it undoubtedly is. See here: https://codepen.io/enyo/pen/NWJdVQa |
It's just a function call, of course it's allowed, it merely has no special properties on its own. This being different from other frameworks is not a good argument either. |
Nice try, but nope, it’s not. Thank you for proving my point that this isn’t allowed. In your example, you just returned a single value, despite how you presented it. It’s no different than just plugging in 8 as the parameter value. |
|
You're also only passing in a single parameter to When it's said to be allowed in JS, it's meant to be syntactically valid. Of course the way it'll work under the hood will be a bit different, that's always how Svelte worked. So what exactly do you mean by it's not valid JS? How it wouldn't make sense at a glance for that expression to be re-evaluated afterwards because you can't have a reference to it without a fn? If so, I don't see the problem, unless you take issue with all the other "magic" that runes brings with it. |
The difference is that passing a value to |
Expressions are used more often as parameter values in JavaScript, e.g.: console.log(a, b, c, (a && b) || c) // Debugging a Boolean expression
throw new Error('Illegal argument: ' + param)
const extension = file.substring(file.indexOf('.') + 1)
// etc. $derived is not really an exception to that, syntax wise |
To play the devil's advocate, the best argument for keeping the current |
I see, I get that! Especially because the compiler does convert the expression inside The discussion that becomes if it is worth it nonetheless. One argument I'd give in favor of the expression syntax, is to make it more immediately obvious that it's different from |
#10240 There's now a PR implementing this as EDIT: ...aaaaand it's closed. This issue should probably be closed too if that's the final decision. |
From the perspective of someone who wants to learn Svelte after runes were announced, I don't think the current design of I've summarized my thoughts into a bullet list:
Ideally I think it would be best to change |
Describe the problem
This is a bit of a rehashing of #9250 prompted by seeing more of this discussion coming up in the Discord
TL:DR there's still animosity around people's preferences regarding the design choice for
$derived
accepting an expression instead of a callback function, and how it becomes slightly less ideal for the scenarios where you want to encapsulate more complex logic that wraps onto multiple lines.Describe the proposed solution
Introduce a
$derived.with
rune, which accepts a callback for determining the derived value instead of an expression.e.g.
Alternatives considered
$computed
rune instead of not being nested under$derived
call
,compute
,using
,from
Importance
nice to have
The text was updated successfully, but these errors were encountered: