fix: ensure subscriptions are picked up correctly by deriveds (#16466)

Increment the version to ensure any dependent deriveds are marked dirty when the subscription is picked up again later. If we didn't do this then the comparison of write versions would determine that the derived has a later version than the subscriber, and it would not be re-run.

Fixes #16311
Fixes #15888
pull/16467/head
Simon H 2 months ago committed by GitHub
parent ce4a99ed6d
commit aabd333d89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure subscriptions are picked up correctly by deriveds

@ -82,6 +82,10 @@ export function createSubscriber(start) {
if (subscribers === 0) {
stop?.();
stop = undefined;
// Increment the version to ensure any dependent deriveds are marked dirty when the subscription is picked up again later.
// If we didn't do this then the comparison of write versions would determine that the derived has a later version than
// the subscriber, and it would not be re-run.
increment(version);
}
});
};

@ -0,0 +1,45 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
test: ({ assert, target }) => {
const [loading, increment] = target.querySelectorAll('button');
assert.htmlEqual(
target.innerHTML,
`
<div>$value: 0</div>
<div>valueFromStore.current: 0</div>
<div>valueDerivedCurrent: 0</div>
<button>Loading</button>
<button>Increment</button>
`
);
loading.click();
flushSync();
assert.htmlEqual(
target.innerHTML,
`
<div>$value: Loading...</div>
<div>valueFromStore.current: Loading...</div>
<div>valueDerivedCurrent: Loading...</div>
<button>Loading</button>
<button>Increment</button>
`
);
increment.click();
flushSync();
assert.htmlEqual(
target.innerHTML,
`
<div>$value: 1</div>
<div>valueFromStore.current: 1</div>
<div>valueDerivedCurrent: 1</div>
<button>Loading</button>
<button>Increment</button>
`
);
}
});

@ -0,0 +1,36 @@
<script>
import { fromStore, writable } from 'svelte/store';
let isLoading = $state(false);
const value = writable(0);
const valueFromStore = fromStore(value);
const valueDerivedCurrent = $derived(valueFromStore.current);
</script>
<div>
$value: {isLoading ? 'Loading...' : $value}
</div>
<div>
valueFromStore.current: {isLoading ? 'Loading...' : valueFromStore.current}
</div>
<div>
valueDerivedCurrent: {isLoading ? 'Loading...' : valueDerivedCurrent}
</div>
<button
onclick={() => {
isLoading = true;
}}>
Loading
</button>
<button
onclick={() => {
$value++;
isLoading = false;
}}>
Increment
</button>
Loading…
Cancel
Save