Skip to content

React hooks

The React surface is small and deliberately effect-free where it matters.

import {
bridge,
provideBridge,
useBridge,
useProvideBridge,
useBridgeState,
useBridgeReady,
} from '@axion/bridgekit';

Returns a stable typed proxy. Safe to destructure; the reference is stable across renders.

const connect = useBridge(ConnectHost);
const result = await connect.installEsim({ url, iccId }); // Promise<'success' | ...>
const codes = connect.otpCodes(); // { subscribe } + AsyncIterable

Scope it explicitly when you need to:

const scoped = useBridge(ConnectHost, { scope: { kind: 'feature', feature: 'connect' } });

Subscribes to a state member and returns { value, status }, backed by useSyncExternalStore. value is total — initial values guarantee it’s never undefined.

const { value: net, status } = useBridgeState(ConnectHost, 'connectivity');
// status: 'initial' | 'available' | 'unprovided'
return <Banner offline={!net.online} stale={status === 'unprovided'} />;

A reactive readiness gate — one hook, not a dance. Readiness is not monotonic; it drops on runtime teardown and returns on reconnect.

const ready = useBridgeReady(ConnectHost);
if (!ready) return <Skeleton />;

Provide a contract from JS (the reverse direction). Auto-unregisters on unmount and is StrictMode-safe — a double mount supersedes harmlessly.

useProvideBridge(LiaFeature, {
getUnreadCount: () => store.unread,
});

Outside React (services, entry points, tests), use the imperative forms:

const connect = bridge(ConnectHost);
await connect.isLoggedIn();
const binding = provideBridge(LiaFeature, impl);
binding.close();

Sets the ambient feature + instance scope for a subtree. The instance tag is the React root view tag — the single source of truth for instance scoping.

<BridgeScopeProvider feature="connect" instance={rootTag}>
{children}
</BridgeScopeProvider>