Skip to content

Commit 82db92f

Browse files
authored
fix: ensure disconnected deriveds correctly connect again (#14899)
* fix: ensure disconnected deriveds correctly connect again * fix: ensure disconnected deriveds correctly connect again
1 parent a91308d commit 82db92f

File tree

4 files changed

+127
-1
lines changed

4 files changed

+127
-1
lines changed

.changeset/happy-plums-greet.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure disconnected deriveds correctly connect again

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,9 @@ export function check_dirtiness(reaction) {
207207
for (i = 0; i < length; i++) {
208208
dependency = dependencies[i];
209209

210-
if (!dependency?.reactions?.includes(reaction)) {
210+
// We always re-add all reactions (even duplicates) if the derived was
211+
// previously disconnected
212+
if (is_disconnected || !dependency?.reactions?.includes(reaction)) {
211213
(dependency.reactions ??= []).push(reaction);
212214
}
213215
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, logs }) {
6+
let [b1, b2, b3, b4, b5] = target.querySelectorAll('button');
7+
8+
b1?.click();
9+
flushSync();
10+
11+
assert.htmlEqual(
12+
target.innerHTML,
13+
`<main><div>Current ID: 1</div>
14+
<div>Name: a</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
15+
<button>Show / Hide</button></div></main>`
16+
);
17+
18+
b2?.click();
19+
flushSync();
20+
21+
assert.htmlEqual(
22+
target.innerHTML,
23+
`<main><div>Current ID: 2</div>
24+
<div>Name: b</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
25+
<button>Show / Hide</button></div></main>`
26+
);
27+
28+
b3?.click();
29+
flushSync();
30+
31+
assert.htmlEqual(
32+
target.innerHTML,
33+
`<main><div>Current ID: 3</div>
34+
<div>Name: c</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
35+
<button>Show / Hide</button></div></main>`
36+
);
37+
38+
b4?.click();
39+
flushSync();
40+
41+
assert.htmlEqual(
42+
target.innerHTML,
43+
`<main><div>Current ID: 4</div>
44+
<div>Name: d</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
45+
<button>Show / Hide</button></div></main>`
46+
);
47+
48+
b5?.click();
49+
flushSync();
50+
51+
b5?.click();
52+
flushSync();
53+
54+
[b1, b2, b3, b4, b5] = target.querySelectorAll('button');
55+
56+
b1?.click();
57+
flushSync();
58+
59+
assert.htmlEqual(
60+
target.innerHTML,
61+
`<main><div>Current ID: 1</div>
62+
<div>Name: a</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
63+
<button>Show / Hide</button></div></main>`
64+
);
65+
66+
b2?.click();
67+
flushSync();
68+
69+
assert.htmlEqual(
70+
target.innerHTML,
71+
`<main><div>Current ID: 2</div>
72+
<div>Name: b</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
73+
<button>Show / Hide</button></div></main>`
74+
);
75+
76+
b3?.click();
77+
flushSync();
78+
79+
assert.htmlEqual(
80+
target.innerHTML,
81+
`<main><div>Current ID: 3</div>
82+
<div>Name: c</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
83+
<button>Show / Hide</button></div></main>`
84+
);
85+
86+
b4?.click();
87+
flushSync();
88+
89+
assert.htmlEqual(
90+
target.innerHTML,
91+
`<main><div>Current ID: 4</div>
92+
<div>Name: d</div><div><button>a</button></div><div><button>b</button></div><div><button>c</button></div><div><button>d</button></div><hr><div>
93+
<button>Show / Hide</button></div></main>`
94+
);
95+
}
96+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script>
2+
const items = [
3+
{ id: 1, name: "a" },
4+
{ id: 2, name: "b" },
5+
{ id: 3, name: "c" },
6+
{ id: 4, name: "d" },
7+
];
8+
let currentId = $state(1);
9+
let currentItem = $derived(items.find(item => item.id === currentId));
10+
let visible = $state(true);
11+
</script>
12+
13+
<main>
14+
{#if visible}
15+
<div>Current ID: {currentId}</div>
16+
<div>Name: {currentItem.name}</div>
17+
{#each items as item}
18+
<div><button onclick={() => { currentId = item.id; }}>{item.name}</button></div>
19+
{/each}
20+
{/if}
21+
<hr>
22+
<div><button onclick={() => { visible = !visible; }}>Show / Hide</button></div>
23+
</main>

0 commit comments

Comments
 (0)