Skip to content

Commit f9f5d3a

Browse files
authored
fix: only update lazy properties that have actually changed (#10415)
* fix: only update lazy properties that have actually changed * code golf * changeset * Add test
1 parent 9aa0ed3 commit f9f5d3a

File tree

5 files changed

+52
-3
lines changed

5 files changed

+52
-3
lines changed

.changeset/rare-worms-hunt.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: only update lazy properties that have actually changed

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,10 +786,20 @@ export function get_first_element(block) {
786786
* @returns {void}
787787
*/
788788
function update_each_item_block(block, item, index, type) {
789+
const block_v = block.v;
789790
if ((type & EACH_ITEM_REACTIVE) !== 0) {
790-
set_signal_value(block.v, item);
791-
} else if (is_lazy_property(block.v)) {
792-
block.v.o[block.v.p] = item;
791+
set_signal_value(block_v, item);
792+
} else if (is_lazy_property(block_v)) {
793+
// If we have lazy properties, it means that an array was used that has been
794+
// proxied. Given this, we need to re-sync the old array by mutating the backing
795+
// value to be the latest value to ensure the UI updates correctly. TODO: maybe
796+
// we should bypass any internal mutation checks for this?
797+
const o = block_v.o;
798+
const p = block_v.p;
799+
const prev = o[p];
800+
if (prev !== item) {
801+
o[p] = item;
802+
}
793803
}
794804
const transitions = block.s;
795805
const index_is_reactive = (type & EACH_INDEX_REACTIVE) !== 0;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let { array } = $props();
3+
</script>
4+
5+
{#each array as number}
6+
<p>{number}</p>
7+
{/each}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
async test({ assert, target }) {
5+
const [b1] = target.querySelectorAll('button');
6+
b1.click();
7+
await Promise.resolve();
8+
9+
assert.htmlEqual(
10+
target.innerHTML,
11+
'<button>add</button><p>1</p><p>2</p><p>3</p><p>4</p><p>0</p>'
12+
);
13+
}
14+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import Child from './Child.svelte';
3+
4+
let array = $state([1,2,3,4]);
5+
6+
const addNew = () => {
7+
array.push(0)
8+
}
9+
</script>
10+
11+
<button onclick={addNew}>add</button>
12+
<Child {array} />
13+

0 commit comments

Comments
 (0)