sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.21k stars 4.09k forks source link

svelte5: keyed each block not working as excepted (worked in svelte4) #10427

Closed FoHoOV closed 6 months ago

FoHoOV commented 7 months ago

Describe the bug

Create an keyed each block then bind a component to an array like this:

{#each store.texts as text, i (text.id)}
    <div>
        <Paragraph bind:this={boundParagraphs[i]} text={text.text}></Paragraph>
        <button onclick={() => boundParagraphs[i].changeBackgroundToRed()}>
            change {text.text} backgroundColor
        </button>
        <button onclick={() => store.remove(store.texts[i].id)}>
            delete {text.text}
        </button>
    </div>
{/each}

If you remove an element from the store store.remove(...) then the onclick will call the wrong boundParagraph. See this repl

Reproduction

  1. go to this repl
  2. click on "delete b1"
  3. click on "change b2 backGroundColor"
  4. see nothing happen (expected behaviour is that b2 changes its color)

Logs

Cannot read properties of null (reading 'changeBackgroundToRed')

System Info

System:
    OS: Windows 11 10.0.22621
    CPU: (16) x64 AMD Ryzen 7 4800H with Radeon Graphics
    Memory: 15.83 GB / 31.42 GB
  Binaries:
    Node: 20.4.0 - C:\Program Files\nodejs\node.EXE
    npm: 9.7.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (121.0.2277.106)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    svelte: ^5.0.0-next.1 => 5.0.0-next.50

Severity

blocking an upgrade

brunnerh commented 7 months ago

Something about the index handling in bind:this seems off. $inspect(boundParagraphs) shows that removal of the first element results in [null, Paragraph] rather than [Paragraph, null] which is the expected result from the second element shifting into the first position.

When removing from the end the progression is correct: [Paragraph, Paragraph] => [Paragraph, null] => [null, null]