Svelte each block different referenced result at event handling function

Viewed 105

I've try below different way to change object props in each block, but having the different result.

First I using inline anonymous function is dose change the cat name in the each block, like step 1 in the below code.

But when I call the event handler in named function it dose not change in each block at all, like step 2.

Finally I try assign props in inline function first then call the named function it change the value too, like step 3.

I am curious why step 2 way is not working to change the value in each block.

Thanks for reading !

<script>
    let cats = [
        { id: 'J---aiyznGQ', name: 'Keyboard Cat' },
        { id: 'z_AbfPXTKms', name: 'Maru' },
        { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
    ];
    const named = (cat) => cat.name = 'named';
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
    {#each cats as cat (cat.id)}
        // step 1. referenced
        <li on:click={()=>cat.name='inline'}>{cat.name}</li>
        // step 2. not referenced
        <li on:click={()=>named(cat)}>{cat.name}</li>
        // step 3. referenced
        <li on:click={()=>{
            cat.name='inline';
            named(cat);
            }}>{cat.name}</li>
    {/each}
</ul>
1 Answers

Svelte's reactivity is triggered by assignments, so updating cat.name won't automatically update references to cats, unless you follow it up with cats = cats, like this:

<ul>
    {#each cats as cat (cat.id)}
        <li on:click={() => { cat.name = 'inline'; cats = cats; } }>{cat.name}</li>
    {/each}
</ul>

Therefore, another solution is to update the cats object itself:

<ul>
    {#each cats as cat, i (cat.id)}
        <li on:click={() => cats[i].name = 'inline'}>{cat.name}</li>
    {/each}
</ul>
Related