svelte
svelte copied to clipboard
False positive binding_property_non_reactive warning when binding to array
Describe the bug
In some cases when using bind:this={array[index]} to bind a component to an array element, it reports the binding_property_non_reactive warning. Making array a $state indeed clears the warning in this case, but in other simpler case it doesn't need to. Is this a bug?
Reproduction
Logs
No response
System Info
Svelte 5.1.3
Severity
annoyance
The warning only triggers in runes mode, Parent.svelte uses $props which enables it.
Thank you. I guess the root of my problem is why does binding an array element to a component needs to be reactive? It seems functioning fine without it if the reactivity is not needed.
The value actually changes. At the moment Parent.svelte is being mounted, Child has not been mounted yet, so the value is undefined at that point. Moments later, when Child is mounted, around the time onMount is called, arr[0] is updated to become the Child object
If arr is a state, when you use $inspect, you can see that happening
I see. I appreciate the explanation. But in my use case, I only use the bound value inside onMount, so the intermediate undefined state is irrelevant to me. You can see here that the value is accessible.
If this message is only to proactively warn people what's going to happen in case they use the value before onMount, I feel it is too much handholding from Svelte. It is like every time people use a raw pointer in C++23 a big red warning from compiler shows up to ask to switch to smart pointer.
Update:
Actually, is there another warning of this called non_reactive_update but to non-array values? The message is <variable_name> is updated, but is not declared with $state(...). Changing its value will not correctly trigger updates. There are many cases these values are used in non-reactive way, such as an event handler. Fortunately this one can be ignored in config.
I encounter this situation quite often in my projects. It's common to store rendered components into an array - just to be able to call some method on them later:
<script>
import Tree from './Tree.svelte';
let { tree } = $props();
let branches = [];
export function updateTree() {
// do something...
for (let branch of branches) branch.updateTree();
}
</script>
Contains {tree.branches.length} branches!
{#each tree.branches as branch, i}
<Tree bind:this={branches[i]} tree={branch}/>
{/each}
I think it really does not need to be reactive in this case.