diff --git a/.changeset/four-flies-hammer.md b/.changeset/four-flies-hammer.md new file mode 100644 index 0000000000..b6d3770a4c --- /dev/null +++ b/.changeset/four-flies-hammer.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve each block fallback handling diff --git a/packages/svelte/src/internal/client/each.js b/packages/svelte/src/internal/client/each.js index 0602d789f7..c37183d7bf 100644 --- a/packages/svelte/src/internal/client/each.js +++ b/packages/svelte/src/internal/client/each.js @@ -119,6 +119,14 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re current_fallback = fallback; }; + /** @param {import('./types.js').EachBlock} block */ + const clear_each = (block) => { + const flags = block.f; + const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0; + const anchor_node = block.a; + reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys); + }; + const each = render_effect( () => { /** @type {V[]} */ @@ -137,7 +145,9 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re if (fallback_fn !== null) { if (length === 0) { if (block.v.length !== 0 || render === null) { + clear_each(block); create_fallback_effect(); + return; } } else if (block.v.length === 0 && current_fallback !== null) { const fallback = current_fallback; @@ -160,17 +170,7 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re false ); - render = render_effect( - /** @param {import('./types.js').EachBlock} block */ - (block) => { - const flags = block.f; - const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0; - const anchor_node = block.a; - reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys); - }, - block, - true - ); + render = render_effect(clear_each, block, true); push_destroy_fn(each, () => { const flags = block.f; diff --git a/packages/svelte/tests/runtime-runes/samples/each-fallback/_config.js b/packages/svelte/tests/runtime-runes/samples/each-fallback/_config.js new file mode 100644 index 0000000000..183184e341 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-fallback/_config.js @@ -0,0 +1,17 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target, component }) { + const [b1] = target.querySelectorAll('button'); + assert.htmlEqual(target.innerHTML, '
abc
'); + flushSync(() => { + b1.click(); + }); + assert.htmlEqual(target.innerHTML, '
Fallback
'); + flushSync(() => { + b1.click(); + }); + assert.htmlEqual(target.innerHTML, '
abc
'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-fallback/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-fallback/main.svelte new file mode 100644 index 0000000000..b0fcc9a86f --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-fallback/main.svelte @@ -0,0 +1,22 @@ + +
+ {#each Object.keys(data) as key} + {key} + {:else} + Fallback + {/each} +
+