Skip to content

Commit b1efd8c

Browse files
authored
fix: improve each block fallback handling (#9914)
1 parent 3a4a091 commit b1efd8c

File tree

4 files changed

+55
-11
lines changed

4 files changed

+55
-11
lines changed

.changeset/four-flies-hammer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: improve each block fallback handling

packages/svelte/src/internal/client/each.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
119119
current_fallback = fallback;
120120
};
121121

122+
/** @param {import('./types.js').EachBlock} block */
123+
const clear_each = (block) => {
124+
const flags = block.f;
125+
const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
126+
const anchor_node = block.a;
127+
reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys);
128+
};
129+
122130
const each = render_effect(
123131
() => {
124132
/** @type {V[]} */
@@ -137,7 +145,9 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
137145
if (fallback_fn !== null) {
138146
if (length === 0) {
139147
if (block.v.length !== 0 || render === null) {
148+
clear_each(block);
140149
create_fallback_effect();
150+
return;
141151
}
142152
} else if (block.v.length === 0 && current_fallback !== null) {
143153
const fallback = current_fallback;
@@ -160,17 +170,7 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
160170
false
161171
);
162172

163-
render = render_effect(
164-
/** @param {import('./types.js').EachBlock} block */
165-
(block) => {
166-
const flags = block.f;
167-
const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
168-
const anchor_node = block.a;
169-
reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys);
170-
},
171-
block,
172-
true
173-
);
173+
render = render_effect(clear_each, block, true);
174174

175175
push_destroy_fn(each, () => {
176176
const flags = block.f;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, component }) {
6+
const [b1] = target.querySelectorAll('button');
7+
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
8+
flushSync(() => {
9+
b1.click();
10+
});
11+
assert.htmlEqual(target.innerHTML, '<div>Fallback</div><button>Toggle</button>');
12+
flushSync(() => {
13+
b1.click();
14+
});
15+
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
16+
}
17+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script>
2+
let data = $state({a:1, b:2, c:3});
3+
let filter = $state(false);
4+
5+
function toggle_filter(){
6+
if(filter) {
7+
filter = false;
8+
data = {a:1, b:2, c:3};
9+
} else {
10+
filter = true;
11+
data = {};
12+
}
13+
}
14+
</script>
15+
<div>
16+
{#each Object.keys(data) as key}
17+
{key}
18+
{:else}
19+
Fallback
20+
{/each}
21+
</div>
22+
<button onclick={toggle_filter}>Toggle</button>

0 commit comments

Comments
 (0)