React — examples
Beyond the minimal binding snippet — the patterns examples/react is built on: composing a data layer, slicing shared fields, and driving the UI off task state.
A data-layer hook
The incidents demo's pattern — compose the bindings once, return plain values. seed.runOnce() ignores repeat triggers while pending/settled; the page query re-runs latest-wins whenever the spec changes.
export function useIncidents(query: QueryArgs) {
const seed = useTask(initIncidents); // one-shot bootstrap
const page = useTask(incidents.queryIncidents); // latest-wins query
const seedProgress = useSharedValue(incidentsMemory, 'signals.seedProgress');
const metrics = useSharedValue(incidentsMemory, 'state.metrics');
useEffect(() => seed.runOnce(), []);
useEffect(() => {
if (seed.settled) page.run(query);
}, [seed.settled, query]);
return {
ready: seed.settled,
seedProgress: seedProgress ?? 0,
metrics: metrics ?? null,
page: page.data,
roundTripMs: page.elapsedMs,
isFetching: page.pending,
};
}Slice a field — render less often
useSharedValue re-renders on every write; a selector + equals limits that to the slice you actually render.
import { shallowEqual } from '@atolljs/core';
// Re-renders only when the {open, critical} pair changes — the other six
// metrics fields can churn without touching this component.
const pressure = useSharedValue(
incidentsMemory,
'state.metrics',
(m) => ({ open: m.open, critical: m.critical }),
{ equals: shallowEqual },
);Task state in the UI
run/runOnce trigger; the snapshot fields — pending, settled, error, elapsedMs — drive the view.
const refresh = useTask(incidents.queryIncidents);
return (
<>
<button disabled={refresh.pending} onClick={() => refresh.run(query)}>
{refresh.pending ? 'scanning…' : 'refresh'}
</button>
{refresh.error ? <p role="alert">{String(refresh.error)}</p> : null}
{refresh.settled && (
<small>round-trip {refresh.elapsedMs?.toFixed(0)}ms</small>
)}
</>
);