React Native SDK Usage
Learn how to integrate Superflag into your React Native or Expo application.
Setup Provider
Wrap your app with SuperflagProvider at the root level:
import { SuperflagProvider } from '@superflag-sh/react-native'
export default function App() {
return (
<SuperflagProvider clientKey={process.env.EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY}>
<YourApp />
</SuperflagProvider>
)
}
import { SuperflagProvider } from '@superflag-sh/react-native'
function App() {
return (
<SuperflagProvider clientKey="pub_...">
<YourApp />
</SuperflagProvider>
)
}
export default App
Using Flags
Basic Usage
Use the useFlag hook to access flag values:
import { useFlag } from '@superflag-sh/react-native'
import { View, Text } from 'react-native'
function MyScreen() {
const showNewFeature = useFlag('new-feature', false)
return (
<View>
{showNewFeature && <NewFeatureComponent />}
</View>
)
}
Type-Safe Flags
Use TypeScript generics for type-safe flag values:
import { useFlag } from '@superflag-sh/react-native'
function ThemeScreen() {
// Boolean flag
const darkMode = useFlag<boolean>('dark-mode', false)
// String flag
const theme = useFlag<string>('theme', 'light')
// Number flag
const fontSize = useFlag<number>('font-size', 16)
// JSON flag
const config = useFlag<{ color: string; size: number }>('ui-config', {
color: '#3B82F6',
size: 14
})
return (
<Text style={{ color: config.color, fontSize: config.size }}>
Theme: {theme}
</Text>
)
}
Checking SDK Status
Use useFlags to check if the SDK is ready:
import { useFlags } from '@superflag-sh/react-native'
import { ActivityIndicator, View, Text } from 'react-native'
function MyScreen() {
const { ready, loading, status, error } = useFlags()
if (loading) {
return <ActivityIndicator />
}
if (error) {
return <Text>Error: {error}</Text>
}
if (!ready) {
return <View />
}
return <YourContent />
}
Provider Props
Configure the provider with these optional props:
| Prop | Type | Default | Description |
|---|
clientKey | string | env var | Public client key (pub_*) |
ttlSeconds | number | 60 | Cache time-to-live in seconds |
Custom TTL
Control how long flags are cached:
// Cache for 5 minutes
<SuperflagProvider clientKey="pub_..." ttlSeconds={300}>
<App />
</SuperflagProvider>
Caching Behavior
The SDK uses AsyncStorage for persistent caching:
- First launch: Fetches flags from API, stores in AsyncStorage
- Subsequent launches:
- Shows cached flags immediately
- Checks for updates in background using ETag
- Only downloads if config changed (HTTP 304 if unchanged)
- Cache expiry: After
ttlSeconds, forces a fresh fetch
This means your app loads instantly with cached flags while staying up-to-date.
Environment Variables
Expo
EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY=pub_prod_...
Then access in your code:
<SuperflagProvider clientKey={process.env.EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY}>
React Native with react-native-config
-
Install
react-native-config:
npm install react-native-config
-
Create
.env file:
SUPERFLAG_CLIENT_KEY=pub_prod_...
-
Use in code:
import Config from 'react-native-config'
<SuperflagProvider clientKey={Config.SUPERFLAG_CLIENT_KEY}>
Always use public keys (pub_*) in mobile apps. Never use SDK keys (sdk_*).
Status Values
The status field from useFlags() can be:
| Status | Description |
|---|
idle | Initial state before fetching |
loading | Fetching flags from API |
ready | Flags loaded successfully |
error | Failed to load flags |
rate-limited | Monthly quota exceeded |
Error Handling
The SDK never crashes your app. Errors are returned in the state:
function MyScreen() {
const { status, error } = useFlags()
if (status === 'error') {
console.error('Failed to load flags:', error)
// App continues with fallback values
}
if (status === 'rate-limited') {
console.warn('Rate limited - using cached flags')
}
// Your component code...
}
Offline Support
The SDK works offline using cached flags:
import { useFlag, useFlags } from '@superflag-sh/react-native'
import NetInfo from '@react-native-community/netinfo'
function MyScreen() {
const [isOnline, setIsOnline] = useState(true)
const feature = useFlag('feature', false)
const { lastFetchedAt } = useFlags()
useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
setIsOnline(state.isConnected ?? false)
})
return unsubscribe
}, [])
return (
<View>
{!isOnline && <Text>Offline mode - using cached flags</Text>}
{feature && <FeatureComponent />}
</View>
)
}
Avoid Re-renders
import { memo } from 'react'
import { useFlag } from '@superflag-sh/react-native'
const ExpensiveComponent = memo(function ExpensiveComponent() {
const config = useFlag('config', { items: 10 })
// This only re-renders when config actually changes
return <HeavyList items={config.items} />
})
Conditional Rendering
function OptionalFeature() {
const enabled = useFlag('optional-feature', false)
// Early return to avoid rendering
if (!enabled) return null
return <ExpensiveFeatureComponent />
}
Next Steps