React Native and Expo
Wire a native app or run the Expo demo against the local hub.
The repository includes a real Expo and Metro integration at examples/expo-demo. It mounts Genie
with the same QueryClient used by QueryClientProvider and also passes its TanStack Router.
Add Genie to an existing app
Import genie-react/hook first in the entry file, before any import that loads React. Mount the
native component once in development:
import { Genie } from 'genie-react/native'
// Inside the app root, using the same QueryClient as QueryClientProvider:
{__DEV__ && (
<Genie
appName="My native app"
url="ws://127.0.0.1:4390/__genie/ws"
queryClient={queryClient}
/>
)}Omit queryClient if the app does not use TanStack Query. The optional router prop accepts a
TanStack Router. React Navigation and Expo Router need their own
app tools for navigation actions.
Start npx @genie-react/cli hub --port 4390 on the development machine. Choose the hub address below
for the target. The init command does not wire Metro or native entry files.
Run the Expo demo
From the repository root, install dependencies once:
pnpm installStart the fixed-port hub in the first terminal:
pnpm --filter @genie-react/expo-demo hubStart one supported local target in a second terminal:
pnpm --filter @genie-react/expo-demo iospnpm --filter @genie-react/expo-demo androidThe package also exposes the Expo launcher when you want to choose the target interactively:
pnpm --filter @genie-react/expo-demo startThe bundled defaults cover local virtual devices only:
| Target | Hub URL |
|---|---|
| iOS Simulator | ws://127.0.0.1:4390/__genie/ws |
| Android Emulator | ws://10.0.2.2:4390/__genie/ws |
For a desktop React Native app running on the development machine, use
ws://127.0.0.1:4390/__genie/ws.
The hub listens on the development machine's loopback interface. A physical device cannot use these loopback examples directly; it requires an external, tested port forward. This repository does not provide a tunnel command. After that forward exists, point Expo at its reachable address:
EXPO_PUBLIC_GENIE_URL=ws://<forwarded-host>:4390/__genie/ws \
pnpm --filter @genie-react/expo-demo startVerify the mounted runtime
After Expo has opened the app, inspect the machine-readable session state from a third terminal and
pin subsequent calls to the one ready Expo demo session:
export GENIE_BRIDGE_URL='ws://localhost:4390/__genie/ws'
status_json="$(
pnpm --filter @genie-react/expo-demo exec genie-react status
)"
jq '{
connected,
ready,
sessionId,
sessions: [
.sessions[]
| {sessionId, app: .app.name, ready, staleMs, domains, toolCount}
]
}' <<<"$status_json"
export GENIE_SESSION="$(
jq -er '
[
.sessions[]
| select(
.ready == true and
.staleMs == null and
.app.name == "Expo demo"
)
] as $matches
| if ($matches | length) == 1
then $matches[0].sessionId
else error("expected exactly one ready Expo demo session")
end
' <<<"$status_json"
)"
pnpm --filter @genie-react/expo-demo exec genie-react call \
react_find_components '{"query":"App","exact":true}' \
| jq '{matches}'
pnpm --filter @genie-react/expo-demo exec genie-react toolsIf session selection fails, keep both long-running terminals open, make sure Expo has mounted the
screen, then rerun the whole status_json block. Do not reuse an empty or stale session ID.
Import genie-react/hook at the very top of the app's entry file (before anything that loads
React), as examples/expo-demo/index.ts does. Without it, tree and inspect tools still work but
every render report stays at zero; react_get_renders reports renderCollection as unavailable in
that case so the empty report is not mistaken for "nothing re-rendered".
The demo source defines increment-button, counter-value, and genie-hub-url test IDs for a
device driver. React Native has no DOM selectors: react_dom_for_component returns native view
details, while browser memory and FPS readings are unavailable. Use device-native performance
evidence for those measurements.
Run the repository's TypeScript and Metro export checks with:
pnpm --filter @genie-react/expo-demo checkThe interaction timeline reports native request timing as unavailable. React events and the supplied Query and TanStack Router integrations can still provide evidence. It does not measure native UI-thread performance or observe every native navigation library.