React Native SDK
Segment membership
This package only evaluates published targeting lists. It has no membership write API and must not hold a Backend application key.
Update members from your backend. Call membership from your backend SDK, not from the React Native app. Flow.
Frontend telemetry
@ops-ai/react-native-toggly 1.4.0 and
@ops-ai/react-native-toggly-core 1.8.0 add one compact reporter to the Core
owner. Configure it through provider props or direct Core configuration.
@ops-ai/react-native-toggly-core 1.9.0 adds enableVariants and
getVariant / getVariantValue; see Hooks → useVariant.
import { useState } from 'react'
import { Pressable, Text, View } from 'react-native'
import { TogglyProvider, useToggly } from '@ops-ai/react-native-toggly'
export default function App() {
const [pricingOpen, setPricingOpen] = useState(false)
return (
<TogglyProvider
appKey="your-app-key"
environment="Production"
enableTelemetry={true}
metricsBaseUrl="https://metrics.toggly.io"
telemetryFlushIntervalMs={45_000}
>
<TelemetryActions onOpenPricing={() => setPricingOpen(true)} />
{pricingOpen && <Text>Pricing</Text>}
</TogglyProvider>
)
}
function TelemetryActions({ onOpenPricing }: { onOpenPricing: () => void }) {
const {
recordUsage, recordView, incrementCounter, setGauge, flushTelemetry,
} = useToggly()
const handleCheckout = async () => {
recordUsage('checkout')
incrementCounter('orders')
setGauge('cartValue', 29.95)
await flushTelemetry()
}
const handleOpenPricing = async () => {
onOpenPricing()
recordView('pricing', 'control')
await flushTelemetry()
}
return (
<View>
<Pressable onPress={handleCheckout}><Text>Checkout</Text></Pressable>
<Pressable onPress={handleOpenPricing}><Text>Open pricing</Text></Pressable>
</View>
)
}
The provider forwards background and inactive AppState transitions to its Core
reporter and disposes that owner on final unmount or configuration replacement.
Direct TogglyService owners must call synchronous dispose() themselves.
AsyncStorage and MMKV companions persist feature data only; they do not own or
persist telemetry. Record explicit views at the navigation boundary that
actually presents them. No usage or view is inferred from rendering. See the
frontend telemetry contract.
Use Toggly's React Native SDK in React Native and Expo applications.
Grab the printable React Native cheat sheet (download PDF) — provider setup, hooks, components, storage, offline.
Session identity
Supply instanceId as a provider prop or Core config field. Update identity
and token props together, clearing instanceId at logout. Direct Core owners
can await service.setContext({ identity: 'user-123', instanceId: 'minted-token' });
use empty strings to clear those fields and groups: [], claims: {} to clear
targeting. await service.setIdentity(null) clears the token and restores the
device identity. The provider's hook does not add a separate reporter. See
session attribution.
Overview
The React Native SDK is a modular feature flags solution designed for React Native and Expo applications. It provides React hooks, context providers, and declarative components for easy feature flag management.
Packages
| Package | Description |
|---|---|
@ops-ai/react-native-toggly | Main SDK with React hooks and components |
@ops-ai/react-native-toggly-core | Core functionality (automatically installed) |
@ops-ai/react-native-toggly-storage-async | AsyncStorage adapter for persistent caching |
@ops-ai/react-native-toggly-storage-mmkv | Storage adapter for MMKV 2 and 3 |
@ops-ai/react-native-toggly-storage-mmkv4 | Storage adapter for MMKV 4 and Nitro (1.0.0+) |
Installation
Main SDK (Required)
npm install @ops-ai/react-native-toggly
# or
yarn add @ops-ai/react-native-toggly
Storage Adapters (Optional)
For persistent feature flag caching, install a storage adapter:
AsyncStorage (Recommended for Expo):
npm install @ops-ai/react-native-toggly-storage-async @react-native-async-storage/async-storage
MMKV 4 with Nitro:
npm install @ops-ai/react-native-toggly-storage-mmkv4@^1.0.0 react-native-mmkv@^4.0.0 react-native-nitro-modules@^0.37.1
cd ios && pod install
MMKV 2/3 for existing hosts (MMKV 3 shown):
npm install @ops-ai/react-native-toggly-storage-mmkv react-native-mmkv@^3.0.0
cd ios && pod install
Both MMKV adapters require a native build; Expo Go is not supported. Expo apps need a development build. Select native dependencies compatible with your React Native release and its Node, iOS, Android, and Nitro requirements. See MMKV 4 setup and migration or the MMKV 2/3 adapter before changing an existing store.
Network State Detection (Optional)
For automatic offline/online handling:
npm install @react-native-community/netinfo
Quick Start
Basic Setup with Toggly.io
import React from 'react';
import { TogglyProvider, Feature, useFeatureFlag } from '@ops-ai/react-native-toggly';
import { createAsyncStorageAdapter } from '@ops-ai/react-native-toggly-storage-async';
// Create storage adapter for persistent caching
const storage = createAsyncStorageAdapter();
function App() {
return (
<TogglyProvider
appKey="your-app-key"
environment="production"
storage={storage}
onError={(error) => {
// Report SDK failures to your app logger, Sentry, or Crashlytics
console.warn('Toggly error:', error);
}}
>
<MyApp />
</TogglyProvider>
);
}
function MyApp() {
const { isEnabled, isLoading } = useFeatureFlag('new-dashboard');
if (isLoading) {
return <LoadingSpinner />;
}
return (
<View>
<Feature featureKey="welcome-banner">
<WelcomeBanner />
</Feature>
{isEnabled && <NewDashboard />}
</View>
);
}
Setup without Toggly.io (Local Feature Flags)
You can use the SDK without connecting to Toggly.io by providing feature defaults:
import React from 'react';
import { TogglyProvider, Feature } from '@ops-ai/react-native-toggly';
const featureDefaults = {
'new-dashboard': true,
'welcome-banner': true,
'experimental-feature': false,
};
function App() {
return (
<TogglyProvider featureDefaults={featureDefaults}>
<MyApp />
</TogglyProvider>
);
}
TogglyProvider
The TogglyProvider component wraps your app and provides feature flag context to all child components.
<TogglyProvider
// Required (if using Toggly.io)
appKey="your-app-key"
environment="production"
// Optional
identity="user-123" // Stable user identifier
groups={['beta']} // Memberships used by targeting rules
claims={{ plan: 'pro' }} // String rule attributes
featureDefaults={{ feature1: true }} // Default values for features
storage={storageAdapter} // Storage adapter for caching
refreshInterval={30000} // Auto-refresh interval (ms)
hooks={[analyticsHook]} // Extensibility hooks
// Event callbacks
onReady={() => console.log('Ready')}
onError={(error) => console.error(error)}
onFlagsChanged={(flags) => console.log(flags)}
>
<App />
</TogglyProvider>
Supply these values on the first provider mount, instead of initializing and then calling a refreshing context setter. Startup captures the context before storage or native lifecycle callbacks can trigger a request. Persisted flags and conditional revisions are accepted only for the matching complete context.
An omitted or empty identity keeps the stored/generated device-ID fallback; empty groups/claims add no memberships or attributes. Use the context-update API for later login or membership changes, not as an extra startup step.
Configuration Options
| Option | Type | Description |
|---|---|---|
appKey | string | Your Toggly.io application key |
environment | string | Environment name (e.g., "production", "staging") |
identity | string | Unique user identifier for targeted rollouts |
groups | string[] | Initial group memberships |
claims | Record<string, string> | Initial string rule attributes |
featureDefaults | Record<string, boolean> | Default feature flag values |
storage | TogglyStorage | Storage adapter for persistent caching |
maxCacheKeys | number | null | Optional LRU cap for identity-scoped feature-flag cache keys (default: unlimited) |
refreshInterval | number | Auto-refresh interval in milliseconds |
enableVariants | boolean | Fetch /evaluated-variants-signed instead of /evaluated-signed and enable useVariant / getVariant / getVariantValue (default: false) |
enableTelemetry | boolean | Compact telemetry; defaults on when an app key is present |
metricsBaseUrl | string | Independent collector; defaults to https://metrics.toggly.io |
telemetryFlushIntervalMs | number | Base interval from 30,000 through 60,000 ms; defaults to 45,000 |
hooks | Hook[] | Extensibility hooks for analytics, etc. |
onReady | () => void | Callback when SDK is initialized |
onError | (error: Error) => void | Callback when an error occurs |
onFlagsChanged | (flags: Record<string, boolean>) => void | Callback when flags change |
For maxCacheKeys behavior, see
Client-side cache limits.
Error reporting and refresh behavior
Use onError to observe fetch, storage, signature, JWK, and refresh failures:
<TogglyProvider
appKey="your-app-key"
environment="production"
storage={storage}
onError={(error) => {
crashlytics().recordError(error);
}}
>
<App />
</TogglyProvider>
After one successful load, refresh failures preserve the last-known-good
effective flags instead of clearing currently rendered UI. Initialization
responses and debug state expose the last error, and feature UI updates through
the effectiveFlagsChanged event. Feature, useFeatureFlag, and
useFeatureGate subscribe to that event automatically.
For the shared reliability contract, see Reliability and Error Handling.
Entity context
Pass a screen entity per widget or hook — not via setIdentity. See Entity & page context.
React Native is a client: registerContext is local. It does not call PUT sdk/{appKey}/contexts.
import { useTogglyService } from '@ops-ai/react-native-toggly'
type Order = { id: string; status: string }
// Call this hook inside a component under TogglyProvider.
function useOrderBadge() {
const toggly = useTogglyService()
return async (order: Order) => {
toggly.registerContext<Order>('Order', (value) => ({
kind: 'Order', key: value.id,
attributes: { Status: value.status },
}))
return toggly.isFeatureOn('OrderBadge', order, 'Order')
}
}
When a flag depends on an entity, resolve it per evaluation; without context, gates fail closed. setIdentity remains user.
Next Steps
- Learn about Hooks for feature flag evaluation
- Explore Storage Options for caching
- Read about User Identity for targeted rollouts
- See Advanced Usage for more features