-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Description
Describe the bug
I have a state like this:
let data = $state({ nested: { id: 123, otherFields: ... }});The ID is used to get more data using an expensive calculation:
const moreData = $derived(expensiveCalculation(data.nested.id))This is meant to rerun whenever ID changes, but unfortunately that's not the case - it reruns whenever data, data.nested or data.nested.id are assigned to. In my case, data is constantly received from the server using a WebSocket:
socket.on('data', (data) => {
data.nested = data
})Although the new data has the same ID, the expensive calculation re-runs every time, causing issues.
The first instinct is to extract the ID into its own derived:
const id = $derived(data.nested.id)It works, but this is in a large component with many top-level fields, so I also tried something else to avoid top-level namespace pollution:
const moreData = $derived.by(() => {
const id = $derived(() => data.nested.id);
return expensiveCalculation(id)
});Bug
This gives me a state_referenced_locally warning, but it works correctly. Nothing seems wrong with this solution IMO, so I think the warning is faulty - reading any state/derived outside of a closure in reactive scopes (effect, derived) should not be a warning.
Feature suggestion
This is somewhat similar in nature to #17308. I wish I could simplify the above solution into this:
const moreData = $derived(expensiveCalculation($derived(data.nested.id)))Reproduction
https://svelte.dev/playground/ddff77a7351e43eda8cf2580ebf97416?version=5.49.1
Severity
annoyance