DEV Community

Svelte: Best practice to combine $derived and $state

Max Core on October 04, 2025

First approximation: let { data } = $props(); let posts = $derived.by(() => { let posts = $state(data.posts); return posts; }); ...
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:

Thread Thread
 
maxcore profile image
Max Core • Edited

@k776
Man, just faced your case.
You mean this would lose reactivity:

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

And as a walkaround it could be:

posts.push(...new_posts)
Enter fullscreen mode Exit fullscreen mode

Have not you consider that?
Do you see downsides here?
Btw don't you have gist for ur box function?
Thx

Thread Thread
 
k776 profile image
Kieran Pilkington • Edited

Yes, that is the case. And yes, using push/shift would work to add/remove singular items, keeping posts reactive. But sometimes you need something like posts = [] to clear the array completely, and in such cases, it would become unreactive to future push/shift calls. The box solution we introduced to our codebase has it's own set of issues. So we're eagerly hoping the Svelte team can provide something like $derived.state(data.posts) or similar to provide a deeply reactive value derived from something else.

Collapse
 
opensas profile image
opensas

I did this small example
with just "let posts = $derived(data.posts)" it seems to work
I can't seem to reproduce the issue

see: svelte.dev/playground/f5645f6cf229...

Collapse
 
opensas profile image
opensas

could you please add a couple examples and explanation showing the problem you are trying to solve?
I still find confusing to understand when stuff is reactive or not

Collapse
 
maxcore profile image
Max Core • Edited

Hi

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