@crosslink/react provides thin bindings over @crosslink/sdk-browser. The hooks add no state machine of their own — the client already owns pairing, reconnection, and transport selection; the hooks just subscribe to it with useSyncExternalStore, so a connection change is reflected on the same render tick.
Setup
Provider
Wrap your app inCrosslinkProvider. It creates a client from options (or accepts an existing client) and exposes connection state through context.
Hooks
useCrosslink()
Returns the full context value: { client, state, rpc, pairedApps, connected }.
useCrosslinkState()
Just the current ConnectionState ("offline", "discovering", "pairing", "connecting", "direct", "turn-relayed", "crosslink-relayed", "reconnecting", "unauthorized", "revoked", "protocol-incompatible").
useCrosslinkRpc()
The RpcClient while a connected state exists, or null otherwise.
useCrosslinkCall()
Calls a method and tracks pending/error. A call started before the connection is up throws immediately rather than queueing — the client already queues idempotent calls across a reconnect, and a second queue here would reorder them.
useCrosslinkEvent(eventName, onEvent)
Subscribes to a host event for as long as the component is mounted and a connection exists. Resubscribes automatically after a reconnect.
useCrosslinkClientState(client)
Subscribes to a specific client’s state without needing a CrosslinkProvider. Useful outside the provider tree, e.g. during pairing.
isConnected(state)
A plain helper — true for "direct", "crosslink-relayed", and "turn-relayed".
Pairing
You do not build a pairing screen.@crosslink/react mounts the same pairing
card every Crosslink application shows:
source points it at the Crosslink system endpoints your host exposes. The card
mints the pairing session, renders the QR and the nine-digit code, refreshes both
before they expire, mints a new one when a device redeems the old one, and lists
and revokes paired devices — no state, effects or fetches of your own. Your
name, icon and colours come from the host’s application block; pass
appName, appIcon or brand only to override one of them here.
The component is a thin mount around createPairingCard; it is the same
implementation a Vue or plain-JS page gets, not a React reimplementation. See
Pairing Card for the full option list.
On the phone
A React mobile app does not run a pairing flow either. Crosslink’s mobile bootstrap does that and hands you a connected channel:null is correct: while there is no channel, Crosslink is rendering
its pairing, install, offline or revoked screen over the page.
Error handling
Best practices
- Use
CrosslinkProviderat the root of the tree that needs Crosslink state - Use
isConnected(state)rather than comparing against a single"connected"string — a connected session can bedirect,crosslink-relayed, orturn-relayed - Show SAS to the user during pairing
- Review capabilities before approving
useCrosslinkEventanduseCrosslinkCallclean up subscriptions and mounted-state tracking automatically on unmount