diff --git a/.changeset/unlucky-baboons-greet.md b/.changeset/unlucky-baboons-greet.md new file mode 100644 index 0000000000..f720e64abf --- /dev/null +++ b/.changeset/unlucky-baboons-greet.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve reconciliation of inert each block rows diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 5753c7cb02..d09d2dac5c 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -373,7 +373,11 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { stashed = []; while (current !== null && current.k !== key) { - (seen ??= new Set()).add(current); + // If the item has an effect that is already inert, skip over adding it + // to our seen Set as the item is already being handled + if ((current.e.f & INERT) === 0) { + (seen ??= new Set()).add(current); + } stashed.push(current); current = current.next; } diff --git a/packages/svelte/tests/runtime-runes/samples/transition-each/_config.js b/packages/svelte/tests/runtime-runes/samples/transition-each/_config.js new file mode 100644 index 0000000000..0dbd62e0ea --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/transition-each/_config.js @@ -0,0 +1,34 @@ +import { flushSync } from '../../../../src/index-client.js'; +import { test } from '../../test'; + +export default test({ + test({ assert, raf, target }) { + const [btn1, btn2] = target.querySelectorAll('button'); + + btn1?.click(); + btn1?.click(); + btn1?.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + '