batch()
Runs fn and updates everything that depends on the states it wrote once, when it returns.
function batch<T>(fn: () => T): T;Usage
import { state, derive, batch } from "qwrk";
const first = state("a");
const last = state("b");
const full = derive(() => `${first.value} ${last.value}`);
<p>{full}</p>;
full.effect((value, oldValue) => console.log(value, oldValue));
batch(() => {
first.value = "Ada";
last.value = "Lovelace";
});
// full recomputes and the <p> updates once
// logs "Ada Lovelace" "a b" onceEvery write is already a batch
Without batch, each write updates the DOM and runs effects before the next line runs. Use batch when several writes belong together, so derives, the DOM and effects update once instead of after each write.
Nesting
Batches can be nested. Inner batches don't update anything themselves: everything updates once, when the outermost one ends.
Reading inside a batch
Derives read inside the batch are already up to date:
const count = state(1);
const doubled = derive(() => count.value * 2);
batch(() => {
count.value = 5;
doubled.value; // 10
});Return value
batch returns what fn returns:
const id = batch(() => {
todos.value.push({ id: 3, text: "Ship it" });
selected.value = 3;
return 3;
});Errors
If fn throws, the writes it made before the error still apply, what depends on them updates, and the error is rethrown. An error thrown by a subscriber while updating is rethrown in its place.
Only the synchronous part
batch groups the writes made while fn runs. Writes after an await inside fn happen later, outside the batch, so they update one by one:
batch(async () => {
loading.value = true; // batched
const data = await load();
items.value = data; // not batched: it updates right away
});