mirror of https://github.com/sveltejs/svelte
fix: avoid unnecessary block effect re-runs after async work completes (#17535)
* add samples for async readable freeze * test updating without changing reference too * fix: treat block effects as maybe dirty in revive() * even simpler - put block effects in maybe_dirty_effects --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>pull/17541/head
parent
e1427aa0c8
commit
fe12ffc2a3
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: avoid unnecessary block effect re-runs after async work completes
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
// ensure in-place object mutations stay reactive in async
|
||||||
|
export default test({
|
||||||
|
skip_no_async: true,
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const button = /** @type {HTMLElement} */ (target.querySelector('button'));
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `<p>count: 1, computed: 10</p><button>mutate</button>`);
|
||||||
|
|
||||||
|
button.click();
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `<p>count: 2, computed: 20</p><button>mutate</button>`);
|
||||||
|
|
||||||
|
button.click();
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `<p>count: 3, computed: 30</p><button>mutate</button>`);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<script>
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
const data = writable({ count: 1 });
|
||||||
|
|
||||||
|
function mutate_count() {
|
||||||
|
data.update(d => {
|
||||||
|
d.count++;
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function compute(d) {
|
||||||
|
return Promise.resolve(d.count * 10);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<p>count: {$data.count}, computed: {await compute($data)}</p>
|
||||||
|
|
||||||
|
{#snippet pending()}
|
||||||
|
<p>pending</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
|
||||||
|
<button onclick={mutate_count}>mutate</button>
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
skip_no_async: true,
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const button = /** @type {HTMLElement} */ (target.querySelector('button'));
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
`<ul><li data-item="1"><span>10</span><span>20</span></li></ul><button>add</button>`
|
||||||
|
);
|
||||||
|
|
||||||
|
button.click();
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
`<ul><li data-item="1"><span>10</span><span>20</span></li><li data-item="2"><span>20</span><span>40</span></li></ul><button>add</button>`
|
||||||
|
);
|
||||||
|
|
||||||
|
button.click();
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
`<ul><li data-item="1"><span>10</span><span>20</span></li><li data-item="2"><span>20</span><span>40</span></li><li data-item="3"><span>30</span><span>60</span></li></ul><button>add</button>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
<script>
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
const items = writable([{ id: 1 }]);
|
||||||
|
|
||||||
|
function add_item() {
|
||||||
|
items.update(arr => [...arr, { id: arr.length + 1 }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function query(item) {
|
||||||
|
return Promise.resolve([item.id * 10, item.id * 20]);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<ul>
|
||||||
|
{#each $items as item (item.id)}
|
||||||
|
<li data-item={item.id}>
|
||||||
|
{#each await query(item) as value}
|
||||||
|
<span>{value}</span>
|
||||||
|
{/each}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{#snippet pending()}
|
||||||
|
<p>pending</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
|
||||||
|
<button onclick={add_item}>add</button>
|
||||||
Loading…
Reference in new issue