React

@atolljs/react — Hooks over useSyncExternalStore. SSR-safe — field reads return undefined until the contract binds on the client.

Install

frontend
npm install @atolljs/core @atolljs/react

Usage

App.tsxfrontend
import { useSharedValue, useTask } from '@atolljs/react';
import { counterMemory } from './counter.memory';
import { counter } from './counter';

export function App() {
  const count = useSharedValue(counterMemory, 'count');
  const increment = useTask(counter.increment);  // client method → latest-wins task

  return (
    <button onClick={() => increment.run(1)}>
      count: {count ?? '…'}
    </button>
  );
}

Binding API

ExportSignatureWhat it does
useObservableuseObservable(source: ObservableValue<T>): TSubscribe to any observable snapshot (task or field).
useSharedValueuseSharedValue(memory, key, select?, options?): T | undefinedBind one shared-memory field to React state; optional selector + equality to slice updates.
useTaskuseTask(task | asyncFn): { data, pending, settled, elapsedMs, error, run, runOnce }Bind an AsyncTask — or any async fn (e.g. a client method, wrapped via toTask) — to state and get its triggers.

Live demo

@atolljs/reactreact/ ↗

If the frame is blank, the examples aren't up — run npm run dev:all (dev servers) or npm run serve:all (built apps) from the repository root.

Notes

  • counter.increment is typed from the worker's defineWorker methods — no task contract to declare.
  • Pass a selector to useSharedValue to re-render only when a slice changes: useSharedValue(memory, 'metrics', m => m.total, { equals: shallowEqual }).
  • Worker-hosted React trees (islands) live in the companion package @atolljs/react-island — see the Islands page under this section.