Svelte 5: $derived rune issue when destructuring
Describe the bug
Reactivity is triggered for unchanged destructured properties of a derived object even though they weren't changed.
Reproduction
<svelte:options runes />
<script lang="ts">
let mainObject = $state({
number: 1,
object: {},
string: "hello"
});
let derivedObject = $derived(mainObject);
setTimeout(() => {
mainObject.number = 2;
}, 3000);
$inspect("derivedObject", derivedObject); // Works as expected and logs again after 3 seconds since a property inside
// the mainObject was changed.
$inspect("derivedObject.string", derivedObject.string); // Works as expected and DOES NOT log after 3 seconds since the
// property that was changed on the mainObject was `number` and not `string`
let { number, object, string } = $derived(mainObject);
$inspect("destructed string property", string); // I'm expecting this to be equivalent to the second $inspect
// which didn't log derivedObject.string but if destructured, and then logged, this last $inspect
// will run again after 3 seconds even though just like the second $inspect `string` property wasn't changed at all.
</script>
The result will still be the same even if you switch the string property with object.
This is inconsistent behavior. The issue is from how $derived works when destructured since the $props rune's output is also an object and that is also used with a destructuring syntax but this issue doesn't happen with $props. The issue can be fixed if each property is separately $derived but this workaround is tedious and you also can't no longer use the ...rest syntax. perhaps the compiler can look at whether the $derived output is destructured or not and if they are destructured, then treat their dependency like it would with
let number = $derived(mainObject.number);
Logs
No response
System Info
System:
OS: Windows 11 10.0.22621
CPU: (16) x64 12th Gen Intel(R) Core(TM) i7-12650H
Memory: 7.04 GB / 15.63 GB
Binaries:
Node: 18.14.2 - C:\Program Files\nodejs\node.EXE
npm: 9.7.1 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Chromium (120.0.2210.144)
Internet Explorer: 11.0.22621.1
npmPackages:
svelte: ^5.0.0-next.40 => 5.0.0-next.40
Severity
blocking an upgrade
There is actually a PR open at the moment to fix this: https://github.com/sveltejs/svelte/pull/10302
There is actually a PR open at the moment to fix this: #10302
OMG. Thanks, for letting me know about it. I made this issue (#10007) for the same reason exactly one month ago and hadn't gotten a proper answer for it ever since so I decided to make another issue and this time focus on the main problem. But you answered it with one line. I'm really waiting for this feature since it affects my work a lot. thanks again
Arguably $inspect("derivedObject.string", derivedObject.string); should rerun after 3 seconds (we closed #10302 because it would not give people a way to opt out of the fine-grained update behavior [some may want the coarse-grained behavior, this is really a matter of opinion / how you think about the system, so both should work], has a few rough edge cases would increase the runtime size)
Fixed by #10488