React
@atolljs/react — Hooks over useSyncExternalStore. SSR-safe — field reads return undefined until the contract binds on the client.
Install
npm install @atolljs/core @atolljs/reactUsage
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
| Export | Signature | What it does |
|---|---|---|
useObservable | useObservable(source: ObservableValue<T>): T | Subscribe to any observable snapshot (task or field). |
useSharedValue | useSharedValue(memory, key, select?, options?): T | undefined | Bind one shared-memory field to React state; optional selector + equality to slice updates. |
useTask | useTask(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
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.