Skip to content

Documentation / @super-line/react / createSuperLineHooks

Function: createSuperLineHooks()

createSuperLineHooks<C, R>(): object

Defined in: index.ts:173

Bind typed React hooks to a contract + role. Create the client once, wrap your tree in the returned <Provider>, then use the hooks inside.

Type Parameters

C

C extends Contract

R

R extends string

Returns

Provider

Provider: (props) => ReactNode

Provides a client to the hooks below. null is legal and means "not connected yet" — the hooks go idle rather than throwing, which is what lets an auth-owned binding render a login screen above them.

Parameters

props
children?

ReactNode

client

SuperLineClient<C, R> | null

Returns

ReactNode

useClient

useClient: () => SuperLineClient<C, R>

Access the client from context (throws outside a <Provider>, or while it holds no client).

Returns

SuperLineClient<C, R>

useCollection

useCollection: <N>(name, query?) => object

Subscribe to a collection subset and track its rows reactively (typed by the contract). Returns the live, ordered + limited rows, the ready/error status of the subscription (so "still loading" and "genuinely empty" are distinguishable, and a denied subscribe is visible), the insert/update/delete/batch mutations, and the underlying handle/sub for anything the wrapped surface doesn't cover. query: null is the explicit idle state (no subscription, no live surface) — distinct from undefined, which subscribes to the whole collection. For joins and complex live queries, use TanStack DB via @super-line/tanstack-db instead — this hook is the thin, single-collection filtered-list surface. Re-subscribes when name or query changes.

Type Parameters

N

N extends string

Parameters

name

N

query?

CollectionQuery | null

Returns

batch

batch: (ops) => Promise<void>

Apply several ops as ONE atomic batch (all-or-nothing on the server).

Parameters
ops

({ row: RowOf<C, N>; type: "insert" | "update"; } | { id: string; type: "delete"; })[]

Returns

Promise<void>

delete

delete: (id) => Promise<void>

Parameters
id

string

Returns

Promise<void>

error?

optional error?: unknown

handle

handle: CollectionHandle<RowOf<C, N>> | undefined

The underlying CollectionHandle (undefined while idle). A window, not ownership.

insert

insert: (row) => Promise<void>

Parameters
row

RowOf<C, N>

Returns

Promise<void>

ready

ready: boolean

True once the initial snapshot has been applied. False while idle.

rows

rows: RowOf<C, N>[]

sub

sub: LiveRowSet<RowOf<C, N>> | undefined

The underlying LiveRowSet (undefined while idle). A window, not ownership — the hook closes it.

update

update: (row) => Promise<void>

Parameters
row

RowOf<C, N>

Returns

Promise<void>

useDoc

useDoc: <N>(name, id, deps?) => object

Open a CRDT document collection (ADR-0007) and track it reactively. The id may be:

  • a string — open that document;
  • null/undefined — the idle state (nothing opens; reads are empty, writes throw);
  • a resolver () => id | Promise<id> — for ids that arrive asynchronously (a registry lookup, a request). It re-runs when deps change (like an effect); an inline arrow is safe. Resolving null/undefined idles; throwing lands on error.

ready is the sequencing signal editors need: it flips true only after the catch-up snapshot has applied, so binding to native before ready is the bug this field exists to prevent. A denied or absent open surfaces on error (it used to be invisible). The handle is closed on unmount.

Type Parameters

N

N extends string

Parameters

name

N

id

string | (() => string | Promise<string | null | undefined> | null | undefined) | null | undefined

deps?

readonly unknown[]

Returns

data

data: DocOf<C, N> | undefined

delete

delete: (path) => void

Parameters
path

(string | number)[]

Returns

void

deleted

deleted: boolean

error

error: unknown

Open denial / absent doc / resolver failure. Cleared when a new open starts.

handle

handle: DocHandle<DocOf<C, N>> | undefined

The reactive DocHandle (undefined while idle/resolving). A window, not ownership — the hook closes it.

native

native: unknown

The engine's native document handle, or undefined before the doc is open. A value, not a getter, so it can be a dependency: it keeps its identity across merges and changes only when the underlying document is replaced, which is exactly when anything bound to it (a rich-text editor) must be rebuilt. Narrow it with the engine package's accessor — yDocOf for Yjs. Sequence the binding on ready, not on presence.

ready

ready: boolean

True once the catch-up snapshot has applied. False while idle, resolving, or loading.

set

set: (value) => void

Parameters
value

DocOf<C, N>

Returns

void

update

update: (partial) => void

Parameters
partial

Partial<DocOf<C, N>>

Returns

void

useEnv

useEnv: () => EnvOf<C, R> | null

The connection's server-vended, client-visible SuperLineClient.env (ADR-0012), tracked reactively: null until the first push (or for a role with no env), then the latest value, re-rendering on every update. Code-only — wire the creds into effects/calls; never render a raw secret.

Returns

EnvOf<C, R> | null

useEvent

useEvent: <E>(event, handler) => void

Subscribe to a server-pushed event for the component's lifetime. Idle (never bound) with no client.

Type Parameters

E

E extends string | number | symbol

Parameters

event

E

handler

(data) => void

Returns

void

useMaybeClient

useMaybeClient: () => SuperLineClient<C, R> | null

The client, or null — what every hook below reads, so a client-less provider idles instead of throwing.

Returns

SuperLineClient<C, R> | null

useRequest

useRequest: <M>(method, ...rest) => RequestState<Output<Requests<C, R>[M]>> & object

The one request hook, TanStack-style. With an input argument it AUTO-FETCHES — on mount, when the input changes (JSON-stable compare), and when the client swaps (new session ⇒ refresh) — unless enabled: false. WITHOUT an input argument nothing ever auto-fires: that is the manual/mutation mode, driven entirely through call(input). The arity is the mode switch, so a no-input request opts into auto-fetching by passing an explicit undefined input.

Type Parameters

M

M extends string | number | symbol

Parameters

method

M

rest

[] | [ClientInput<Requests<C, R>[M]>, object]

Returns

useSubscription

useSubscription: <T>(topic) => EventData<TopicsOf<ServerMessages<C, R>>[T]> | undefined

Subscribe to a topic and return its latest value (or undefined before the first message / with no client).

Type Parameters

T

T extends string | number | symbol

Parameters

topic

T

Returns

EventData<TopicsOf<ServerMessages<C, R>>[T]> | undefined

Example

tsx
const { Provider, useRequest, useEvent, useSubscription } = createSuperLineHooks<typeof api, 'user'>()

function Root() {
  const [client] = useState(() => createSuperLineClient(api, { url, role: 'user' }))
  return <Provider client={client}><Room /></Provider>
}

Released under the MIT License.