React Native SDK
React Native quickstart for @layers/amba-react-native — install, configure, session storage, push registration, Apple/Google sign-in. Bare-RN-first; Expo flavors shown as sub-tabs.
@layers/amba-react-native is the React Native SDK. Same API as every other Amba SDK; with a secure token store installed, users stay signed in across app restarts (see Where session tokens are stored).
This page is bare React Native first — every snippet uses non-Expo libraries by default, with the Expo equivalent as a sub-tab. If you're on the Expo managed workflow, use @layers/amba-expo instead — same runtime, plus a config plugin that wires native config at prebuild time.
1. Install
Core package (both flavors):
Peer libraries for Apple/Google sign-in and push:
The runtime call into @layers/amba-react-native is identical either way — once you have an identity token (Apple) or an id token (Google) or a push token (APNs/FCM), pass it to Amba.auth.signInWithApple(identityToken) / Amba.auth.signInWithGoogle(idToken) / Amba.push.register(...) unchanged. Only the producer library differs. When the sign-in request carried a nonce, pass the raw value too: Amba.auth.signInWithApple(identityToken, { nonce }) (see sign-in nonce).
Crypto setup
Required. Hermes (React Native's default JS engine) does not ship crypto.getRandomValues. Amba uses it to generate identifiers that need to be unpredictable, such as the anonymous id that signs an anonymous user back in. Without the polyfill, Amba.configure() throws SecureRandomUnavailableError (from @layers/amba-react-native 4.0.14).
Install the polyfill:
Then import it once, as the very first import in your app's entry file, before any other Amba imports:
Order matters. The polyfill installs crypto.getRandomValues on the global object as a side effect of being imported; if Amba loads first, it captures the (missing) global and the polyfill never takes effect. Put the import on line 1.
A one-shot console warning fires at runtime if Amba sees the fallback path engaged — that's your signal the polyfill import is missing or out of order.
Metro config for monorepos
If you consume @layers/amba-react-native via pnpm/yarn workspaces, point Metro at the workspace root so it can resolve hoisted dependencies:
Without watchFolders + resolver.nodeModulesPaths, Metro only looks in this package's local node_modules and fails with "Unable to resolve module @layers/amba-react-native".
2. Configure on app boot
Put your credentials in a .env file at the project root:
react-native-config injects them at build time into Config.AMBA_PROJECT_ID / Config.AMBA_CLIENT_KEY (no process.env indirection needed). See the react-native-config setup guide for the iOS / Android native config wiring (one-time).
Amba.configure() is idempotent — calling it again with the same key is a no-op.
Where session tokens are stored
The session and refresh tokens go wherever the tokenStorage option says. The anonymous id and user id stay in AsyncStorage in every mode.
tokenStorage | Tokens live in | After a restart |
|---|---|---|
"secure" (default) | The iOS Keychain / Android Keystore, through secureStorage when you pass one, otherwise react-native-keychain when it is installed. With neither, memory only, plus one warning. | Signed in with a secure store, signed out without one |
"memory" | Memory only | Signed out |
"asyncStorage" | Plain AsyncStorage, which anyone who can read the app's files or an unencrypted backup can copy | Signed in |
Install react-native-keychain (as above) to keep users signed in across launches. To use another keystore-backed module, pass an adapter with getItem, setItem and removeItem:
Choose tokenStorage: "asyncStorage" only when no secure store can be installed and signing in again on every launch is unacceptable: a stolen backup then carries a session that stays usable for 30 days and refreshable for 90. Tokens an earlier SDK version left in AsyncStorage move into the secure store on the first launch after the upgrade (or stay in memory for that launch when there is none), and the plaintext copy is removed. If sign-out can't clear the secure store, the SDK starts a new anonymous id so the stored session can't come back.
While the secure store can't be read (an iOS device that has not been unlocked since it restarted), a call that would replace the stored session with a new anonymous user fails with SECURE_STORE_UNAVAILABLE and leaves that session in place; retry once the device is unlocked. When a launch finds no tokens for a session that had signed in or linked an identity (memory storage, or a secure-store entry that is gone), the device starts a new anonymous id, as a sign-out would.
3. First event + first sign-in
Amba.events.track is authenticated server-side. Mint an anonymous session before the first track call:
Identical code on bare RN and Expo — @layers/amba-react-native is the only import either flavor needs at this layer. The session is restored on later launches when a secure token store is installed, as described in Where session tokens are stored.
4. Sign in with Apple
Add the Sign In with Apple capability in Xcode (Signing & Capabilities → + Capability → Sign In with Apple). One-time per target.
5. Sign in with Google
Configure your OAuth client IDs in Google's API credentials console. The iOS client ID and Android client ID must match the bundle ID / package name of each platform build.
6. Push registration
@notifee/react-native is a renderer for incoming notifications — it does not produce APNs/FCM tokens. The tokens come from the platform-native push module: PushNotificationIOS (built into React Native) for APNs, and Firebase Messaging (@react-native-firebase/messaging) for FCM. Notifee handles permissions on both platforms.
Call this once after sign-in (or after the user opts in). Tokens rotate; re-call on app cold-start to refresh. On real iOS hardware only — APNs token issuance is disabled on the simulator.
7. Collections
Same DSL as the web SDK — identical code on bare RN and Expo:
@layers/amba-react-native carries the full where DSL (eq, ne, gt, gte, lt, lte, in, notIn, like, ilike, isNull, isNotNull, plus and, or, not) — see the Web SDK page for the full operator surface.
8. Storage uploads
Storage uploads use the standard presign → PUT → commit flow. Where the flavors diverge is in how you read a local file into bytes — bare RN typically uses react-native-blob-util (full-featured filesystem + multipart helpers); Expo uses expo-file-system.
Bare React Native vs. Expo workflow
| Concern | Bare RN | Expo managed |
|---|---|---|
| Install | pnpm add + pod-install | npx expo install |
| Native iOS configuration | Edit Info.plist / Entitlements.plist directly | Use the @layers/amba-expo config plugin |
| Native Android configuration | Edit AndroidManifest.xml directly | Use the @layers/amba-expo config plugin |
| Apple sign-in capability | Add via Xcode → Signing & Capabilities | expo-apple-authentication adds it on expo prebuild |
| Push entitlements | Add via Xcode + Google Services file | @layers/amba-expo plugin adds APNs entitlement + reads google-services.json |
| Best for | Existing native iOS / Android codebases adding RN | Greenfield apps, EAS Build, OTA updates |
Either workflow runs the same @layers/amba-react-native runtime — the difference is only in how native config files get written.
4.0 surface highlights
The full 4.0 namespace set is the same shape as @layers/amba-web:
Common pitfalls
Amba.configure()called inside a component render — calls happen on every re-render and racily replace the singleton. Always wrap inuseEffect(..., [])or call at module scope above your root component.- Push registration on simulators — APNs requires a real device. In bare RN,
PushNotificationIOS.requestPermissions()resolves without issuing a token on the simulator; in Expo,Notifications.getDevicePushTokenAsyncreturnsnull(the Expo snippet short-circuits whenDevice.isDeviceis false). Guard accordingly. - Users signed out after every launch — no secure token store is installed, so the tokens live in memory. Install
react-native-keychain, pass asecureStorageadapter, or opt intotokenStorage: "asyncStorage"(see Where session tokens are stored). - Hermes performance — on Hermes, React Native 0.73+ is required for full SDK performance. Earlier versions fall back to a slower JS-only path that's ~3× slower.
See also
- Expo SDK — the config plugin layer on top of this package.
- Client API reference — HTTP endpoint reference for every namespace.
- Code samples — same operations side-by-side with the other 7 SDKs.