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.

useIncidents.tsfrontend
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.

frontend
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.

frontend
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>
    )}
  </>
);