DEV Community

Max Core
Max Core

Posted on

Svelte: Best practice to combine $derived and $state

First approximation:

let { data } = $props();
let posts = $derived.by(() => {
    let posts = $state(data.posts);
    return posts;
});
Enter fullscreen mode Exit fullscreen mode

It is not documented, and me personally obtained it here:
https://discord.com/channels/457912077277855764/1406193849423888415/1406241130726690837
From mjadobson, approved by Patrick.

Others advice, for semantics and linters, that let better be const:

let posts = $derived.by(() => {
    const posts = $state(data.posts);
    return posts;
});
Enter fullscreen mode Exit fullscreen mode

Performance may depend on an engine.

Another way to make it one line:

let posts = $derived.by(() => { const _ = $state(data.posts); return _ });
Enter fullscreen mode Exit fullscreen mode

And now, while copy-paste, there are 2 places left to change, not 4.

For sure, it COULD NOT be:

let posts = $derived.by(() => $state(data.posts));
Enter fullscreen mode Exit fullscreen mode

Since:

$state(...) can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.


Probably it'll be nice to have $reactive rune one day, combining both or something


I've one have more elegant solution — please share
Thx

Top comments (6)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

What's the use case? What problem does this solve?

Collapse
 
maxcore profile image
Max Core • Edited

$derived is shallow reactive posts = new_value,
not deeply reactive posts.title = new_value,
unless you combine it with $state

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

I see. But this is rarely needed, I'd say. Only if you are modifying the derived value.

Anyway, thanks for clarifying.

Thread Thread
 
k776 profile image
Kieran Pilkington

"rarely needed" - Actually we were using props in $state throughout our app, and then the new warning against doing that showed up (which did infact reveal we had issues in our code). So our first pass was to change all our $state(prop) syntax to the syntax shown in the OP. Problem with OPs approach is that if you reassign the $dervied var, it would lose the $state aspect. So we ended up creating a box function that wraps it in a proxy with some checks and setter methods to prevent it from ever losing $state, but the whole thing is clunky. Ideally Svelte would support something natively ($derived.from(prop) or $derived.state(prop), or $state.from(prop), or something).

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Interesting. Indeed. Sounds like an inconsistency at the (Svelte) library level. You might want to start a discussion or an issue about it in Svelte's GH repository.

Thread Thread
 
k776 profile image
Kieran Pilkington

There are a couple of open discussions around this, namely: