svelte icon indicating copy to clipboard operation
svelte copied to clipboard

False positive binding_property_non_reactive warning when binding to array

Open CrendKing opened this issue 1 year ago • 4 comments

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

Minimum playground demo

Logs

No response

System Info

Svelte 5.1.3

Severity

annoyance

CrendKing avatar Oct 27 '24 09:10 CrendKing

The warning only triggers in runes mode, Parent.svelte uses $props which enables it.

brunnerh avatar Oct 27 '24 15:10 brunnerh

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.

CrendKing avatar Oct 27 '24 20:10 CrendKing

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

MotionlessTrain avatar Oct 27 '24 22:10 MotionlessTrain

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.

CrendKing avatar Oct 27 '24 22:10 CrendKing

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.

sourcecaster avatar Jan 23 '25 17:01 sourcecaster