React hooks

@conexus-x/sdk/react — a separate entry point from the framework-free core, so a view written in Svelte, Vue or plain JS never pays for React it does not use. A view is fundamentally a subscription problem: the module moves under it as the person switches collection, a colleague edits a cell, the theme flips. Hooks are the right shape for that; hand-rolled listen/unsubscribe in useEffect is where the leaks live.

Connection

HookReturns
useConnection(){ status: "connecting" | "ready" | "error", connection, error }
useViewContext()The live ViewContext, re-rendering as the person moves around the module.
useSettings<T>()This view instance's configured settings, typed to your own shape.
useSelection()string[] — the rows currently selected on the module.
useScope(scope)boolean — was this scope actually granted? Renders false until connected, never throws.

Data

Each of these wraps the general-purpose useConexusQuery, refetching automatically on the realtime event that could plausibly have changed its data — never on an unrelated one.

HookRefetches on
useRecords(collectionId)record or recordValue changes
useModules(workspaceId)module changes — the hook a workspace-level view needs, since it has no collection to list records from
useCollections(moduleId)collection changes
useColumns(moduleId)column changes

Each returns { data, loading, error, refresh }. Build your own with useConexusQuery(fetcher, options) when none of the above fit — same shape, your own fetcher and refetch condition.

tsx
const { data: records, loading, error, refresh } = useRecords(context?.collectionId);

// A custom one, refetching only on an amendment:
const { data } = useConexusQuery(
    (cx) => cx.api.amendments.list(recordId),
    { deps: [recordId], shouldRefetch: (e) => e.entity === "amendment" }
);

Subscribing directly

useConexusEvent(topic, handler) — for anything the data hooks above do not cover. The handler is held in a ref internally, so passing an inline arrow never resubscribes on every render.

Chrome

HookWhat it does
useAutoResize(ref?)Keeps the iframe as tall as the content. Opt-in, like the underlying call.
useCommands(){ notice, openRecord, confirm, navigate, copyToClipboard } — bound and stable across renders.

One client per page

Every hook shares a single client memoised at module scope — a view iframe has exactly one parent host, so a context provider would be ceremony around a value that can never legitimately differ between two subtrees. Pass an explicit client argument to any hook only if you genuinely need a second one.