React bindings
React bindings for i99dash — provider component and one hook per family. Every hook accepts a fallback for SSR / no-host / unsupported-family graceful degradation.
React bindings on top of i99dash. Single
entry point — there's nothing here that wouldn't be tree-shaken if
a consumer only uses one hook, so a flat export keeps the public
surface visible at a glance.
pnpm add i99dashThe React bindings live behind the i99dash/react subpath of the
single i99dash package. No separate install.
At a glance
import { useState } from 'react';
import { MiniAppProvider, useCarStatus, useMedia } from 'i99dash/react';
import { createClientOrSSR } from 'i99dash';
export default function App() {
// Lazy init runs once per mount — stable reference across re-renders
// so MiniAppProvider doesn't tear down and re-open the bridge sub.
const [client] = useState(() => createClientOrSSR());
return (
<MiniAppProvider client={client}>
<Dashboard />
</MiniAppProvider>
);
}
function Dashboard() {
const { data: status } = useCarStatus();
const { data: media } = useMedia();
// External data is plain fetch() against a declared manifest.network
// origin — no SDK hook wraps it.
return <Layout status={status} media={media} />;
}Provider
Mount once at the root of your tree. Every hook below reads the client through React context.
| Component | Purpose |
|---|---|
MiniAppProvider | Binds the client. null is a first-class value — pass null for SSR, jsdom, or Storybook stories. |
useClient() | Escape hatch for one-off client flows that don't fit a dedicated hook. |
Family hooks
Each hook has the same shape:
const { data, error } = useFooBar({ fallback?: T });While the bridge isn't reachable (SSR, jsdom, the host doesn't ship
the family), data is the fallback you passed in (or undefined)
and error is null. No throws.
| Hook | Family scope | Returns |
|---|---|---|
useMiniAppContext | — (always available) | { data, error, loading } of MiniAppContext |
useCarStatus | car.status.read | { data, error } of CarStatus |
useMedia | media.read | { data, error } of MediaSnapshot |
useClimate | climate.read | { data, error } of ClimateSnapshot |
useVehicleDiagnostics | vehicle.diagnostics | { data, error } of VehicleDiagnosticsSnapshot |
useVehicleEnvironment | vehicle.environment | { data, error } of VehicleEnvironmentSnapshot |
useSystem | system.read | { data, error } of SystemSnapshot |
useConnectivity | connectivity.read | { data, error } of ConnectivitySnapshot |
useLocation | location.read | { data, error } of LocationSnapshot |
useNavigation | nav.read | { data, error } of NavigationSnapshot |
SSR / no-host fallbacks
Every hook accepts an optional fallback so the component renders a
sane shape when there's no bridge:
const { data: ctx } = useMiniAppContext({
fallback: { locale: 'en', isDark: false, /* ... */ },
});
const { data: status } = useCarStatus({
fallback: { speedKmh: 0, doorsLocked: true, staleness: 'very_stale', /* ... */ },
});This is the right tool for:
- Next.js / Nuxt SSR — server render shows the fallback; the hook re-renders with real data after hydration.
- Storybook / jsdom — the host bridge doesn't exist; the hook
stays on
fallbackindefinitely without throwing. - Older host builds — the family isn't available yet; same graceful-degradation as the unsupported-host case.
For dynamic capability checks (e.g. do not even try to call
useMedia if the host doesn't ship it), reach for
client.has(scope) at app start.
Source
- Package:
i99dash/react - File:
src/react/index.tsx
Related
i99dashindex — the underlying client- React + Next.js setup — full project walkthrough
- Subscriptions guide — same lifecycle patterns the hooks wrap