Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/happy-eggs-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure each block consistency to internal mutations to the collection
8 changes: 8 additions & 0 deletions packages/svelte/src/internal/client/dom/blocks/each.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
// continue in hydration mode
set_hydrating(true);
}

// When we mount the each block for the first time, the collection won't be
// connected to this effect as the effect hasn't finished running yet and its deps
// won't be assigned. However, it's possible that when reconciling the each block
// that a mutation occurred and it's made the collection MAYBE_DIRTY, so reading the
// collection again can provide consistency to the reactive graph again as the deriveds
// will now be `CLEAN`.
get_collection();
});

if (hydrating) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { flushSync } from 'svelte';
import { test } from '../../test';

export default test({
async test({ assert, target }) {
const button = target.querySelector('button');

button?.click();
flushSync();

assert.htmlEqual(
target.innerHTML,
`<button>Add</button><label><input type="checkbox"></label><label><input type="checkbox"></label>`
);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let { value = $bindable() } = $props();
</script>

<label>
<input type="checkbox" bind:checked={value} />
</label>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script>
import Checkbox from './checkbox.svelte';

let foo = $state({})

const schema = $state({
foo: true,
})

function retrieveSchema() {
const cloned = { ...schema }
for (const key of Object.keys(foo)) {
cloned[key] = key
}
return cloned
}

const keys = $derived(Object.keys(retrieveSchema()));
let nextKey = 1;
</script>

<button onclick={() => {
foo[nextKey++] = true
}}>Add</button>

{#each keys as key (key)}
<Checkbox bind:value={foo[key]} />
{/each}