Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Todo bind:this={todo.ref} ... /> leads to undefined when todos array is mutated #11272

Open
michael opened this issue Apr 21, 2024 · 3 comments
Milestone

Comments

@michael
Copy link

michael commented Apr 21, 2024

Describe the bug

While initially all todo.ref class fields are set properly, as soon as I mutate the todos array (e.g. when doing todos.splice(1,0, new Todo('Clean toilet')) the todo.ref is undefined. I had a really hard time reproducing this, as for other indexes it works (like when I do todos.push(new Todo('Clean toilet')).

Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE51UwY7bOAz9FcJbwA4Q2N1rmgx221MPu5ddoIfJoNVYdKyOQhkSPdnC8L8vKNlOMkinRQ9JFOqRIh8fOWSNsRiyzf2QkTpitsn-7LpsnfG3Tv6EZ7SM2ToLrve1WLah9qbjuz3t2Rw75xn-ddr95TRaaLw7Ql5Wi6VMAcqvIX_3wuMKPOGuQAOwqZ9gTMD9lMs-ixj5WGRgp12AHbwJrBiL-3jHhKdzVkX-SYUWtAkthny1vg0xHUJjnfPfQ7z3hg7gegb2KrT5SlAPK8mG9qzCN6qh6alm4wiU1p8JT58lvWIFQ4pYVWAooI-QzgUjh3RVOwosNtjB7--gqqA4GW7Fsos1lhbpwC0YhpPzT0EeBoBEQBk6a2oskgnEaz2f3y6nFwV9sKgI2BmLHIsWzCqxy-lbnZTh2IZiFZOK_3tiY4FbhLpVdEBoVYDOu04dFKMGRRpqd-wcIXGAVj0jPCISeCSNHvXCxj-I8GhIb7g1YTdILaXHZgRDcCGLM0XOYmndociX-OCxAddAY3xIctjk68TK_dsHiVa2aK0rVnNpVQXyHKD3zgd4xFr1ASeXzoXoBCZATxobQ3O-r78v5EoIMOGcwBztOoVxT9vqPEa0feyZHYGj2pr6aTdcqme8-yDGbZVAd3safkNVt5PyVYiHNZhRQm_jZEUiR6gEXAl43FO2zo5Om8agzjbsexzXy8iL0y_M_Cevug791SBPtlvz_JEI_dXkL5YreBqFIbE5ymyLtkIh5F3zdvFgzG2bwmzOzUm6Wt4ZZ2puiq66E91vq-uwPyLucs-dSfwaLgnE_yIDGhvVW4baqhDSEoybQaKdd1ieJ5mIsF4aZ3p8X7PzhTgu20XKKadQ8jNrbXytgoWaX-j_9zf4ay2U-4mPZV1O4zFX4pF7T_AlmtMrb1KfJOvxy-0p0uY5Zvi3OuIGLvAClMsfdXLq-c8yMRdZt8Zqj_S6VidposXjWZi5Ns_5GKMNf6TtuIQrVqnCK78bNTyM_wMV3w_ixQcAAA==

Logs

running Svelte compiler version 5.0.0-next.110
103Fetch finished loading: GET "<URL>".
VM351 about:srcdoc:96 component ref of first todo: hello from Wash dishes
playground:output:3492 Uncaught (in promise) TypeError: todos[pos].ref.hello is not a function
    at HTMLButtonElement.add_new_todo (playground:output:3492:63)

System Info

System:
    OS: macOS 14.2.1
    CPU: (8) arm64 Apple M2
    Memory: 107.00 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.10.0 - /usr/local/bin/node
    npm: 10.2.3 - /usr/local/bin/npm
  Browsers:
    Chrome: 124.0.6367.62
    Safari: 17.2.1
  npmPackages:
    svelte: 5.0.0-next.110 => 5.0.0-next.110

Severity

blocking all usage of svelte

@michael michael changed the title <Todo bind:this={todo.component_ref} ... /> leads to undefined when todos array is mutated <Todo bind:this={todo.ref} ... /> leads to undefined when todos array is mutated Apr 21, 2024
@paoloricciuti
Copy link
Contributor

With a keyed each block it works: https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAA51UTY_TMBD9K6OAlESqEriWdsXXhQNcAHHYrsAbTxqz7jiyJ1tWUf47sp2kDZQFcWjrjt98Pb-ZPqmVRpesr_uExAGTdfKqbZNVwg-t_-PuUTMmq8SZzlbesnGVVS1f7WjH6tAay_DJSPPeSNRQW3OAtChnSxEDFN9d-uIXjwV4xC1APbCq7mCIwN1Yyy4JGP_RyMBGGgdbeOpYMGbX4Y4Jj6eqsvSLcA1I5Rp0ab66DFEtQq2NsX9CvLaK9mA6BrbCNWnuUTe5r4Z2LNwDVVB3VLEyBELKr4THr768LIc-RixLUOTQBkhrnPKHeFUZcuxtsIXnL6AsITsqbrxlG3osNNKeG1AMR2PvnE8MAJGAwrVaVZhFE3iv1XR-Np9-aeiNRkHARmnk0LTH5JFdjt_iKBSHZ8jyUFT43xErDdwgVI2gPUIjHLTWtGIvGCUIklCZQ2sIiR004h7hFpHAIkm0KGc2PiLCrSK55ka5be97KSzWAyiCM1mcKDIaC232WTrHB4s1mBpqZV2UwzpdRVaun934aEWDWpssn1orS_DpAK011sEtVqJzOLq0xgUnUA46klgrmup9PL8n14cA5U4FTNGWJQw72pSnMaLNbcdsCAxVWlV32_5cPcPVG2_clBF0taP-CYqqGZUvXDisQEEW6FMyH3ySTZixQOkApXcrvduwo2SVHIxUtUKZrNl2OKzm4fdO_zH9X6xoW7SLkR5tlyb7HRHaxQ6YLQt4HIo-8jr4Kfcqc5mnccngWcJQ2yaGWZ-eKSpszjNM1FyUX3nlJ2BTLsP-jbjzjXci8bs7JxB_BAYk1qLTDJUWzsV1GHaEj3baZmkaBeMl9ptRSdhCZR9aNoUVJM3h8-d3b7NpIQXubFexsZmPOi8h32sx5vE_kySHx9qbefsPcfx50T_2vv5-JGvequMUTZ1Y5M4SfAvmmOVpfERf9fDt8rBJdR8q_CAOuIYzvAf6y7898yiIf2ViarJqlJYW6XEhj7pFjYeTalOp7tMhROtfxiU6h8vy2OHC70IPN8NP41USPewHAAA=

This also kinda explain why position matters. At .length you are pushing in a completely new position. With splice you are "replacing an old one" so the component at position 2 is not unmounted but the prop is replaced and the same goes with the component inside. Is the same component so bind:this is probably not triggered.

Not sure if this is still a bug tho.

@michael
Copy link
Author

michael commented Apr 21, 2024

Thanks a lot for spotting this! We can of course provide a unique key when that solves the issue. Still, I guess I'd expect this to work without providing a key too (with less efficient reconciliation).

So leaving this open for the Svelte team to decide if there's action needed (could be a fix, or a warning?).

Attaching our Twitter discussion for context:

https://twitter.com/PaoloRicciuti/status/1782036498780414003

@Rich-Harris Rich-Harris added this to the 5.0 milestone Apr 21, 2024
@dummdidumm
Copy link
Member

Reduced reproducible.

The behavior is the same in Svelte 4, it doesn't work there, too.

I'm inclined to mark this as "works as designed". The reason is that the each array by default is checking the array index for whether or not the whole thing needs to be recreated. Since the indexes only increase, the existing ones never change and so bind:this has no indication to update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants