Hooks
The React Native SDK provides several React hooks for evaluating feature flags.
useFeatureFlag, useFeatureGate, and the context from useToggly re-evaluate
when remote flags refresh or when device-local post-filter gates change via
notifyLocalGatesChanged(). See Post-filter gates
and Advanced → Device-local post-filter gates.
useFeatureFlag
Check a single feature flag status.
import { useFeatureFlag } from '@ops-ai/react-native-toggly';
function MyComponent() {
const { isEnabled, isLoading, error } = useFeatureFlag('feature-key');
if (isLoading) return <Loading />;
if (error) return <Error message={error.message} />;
return isEnabled ? <NewFeature /> : <OldFeature />;
}
Return Value
| Property | Type | Description |
|---|---|---|
isEnabled | boolean | Whether the feature is enabled |
isLoading | boolean | Whether the SDK is still loading |
error | Error | null | Any error that occurred |
Options
const { isEnabled } = useFeatureFlag('feature-key', {
defaultValue: false, // Value to use while loading
});
useFeatureGate
Check multiple feature flags with all or any requirement.
import { useFeatureGate } from '@ops-ai/react-native-toggly';
function MyComponent() {
// All features must be enabled
const { isEnabled: allEnabled } = useFeatureGate(
['feature1', 'feature2'],
{ requirement: 'all' }
);
// At least one feature must be enabled
const { isEnabled: anyEnabled } = useFeatureGate(
['feature1', 'feature2'],
{ requirement: 'any' }
);
// Negate the result (show when features are OFF)
const { isEnabled: noneEnabled } = useFeatureGate(
['feature1', 'feature2'],
{ requirement: 'all', negate: true }
);
}
Options
| Option | Type | Default | Description |
|---|---|---|---|
requirement | 'all' | 'any' | 'all' | Whether all or any features must be enabled |
negate | boolean | false | Inverts the result |
defaultValue | boolean | false | Value while loading |
useToggly
Access the full Toggly service for advanced operations.
import { useToggly } from '@ops-ai/react-native-toggly';
function MyComponent() {
const {
toggly, // TogglyService instance
isReady, // SDK is initialized
isLoading, // Currently loading
error, // Initialization error
isFeatureOn, // Function to check feature
setIdentity, // Set user identity
refresh, // Manually refresh flags
getFeatureValue, // Get raw feature value
} = useToggly();
const handleLogin = async (userId: string) => {
await setIdentity(userId);
};
const handleLogout = async () => {
await setIdentity(null);
};
const handleRefresh = async () => {
await refresh();
};
// Imperative feature check
const isPremium = isFeatureOn('premium-features');
}
Return Value
| Property | Type | Description |
|---|---|---|
toggly | TogglyService | The underlying Toggly service instance |
isReady | boolean | Whether the SDK is fully initialized |
isLoading | boolean | Whether the SDK is currently loading |
error | Error | null | Any initialization error |
isFeatureOn | (key: string) => boolean | Check if a feature is enabled |
setIdentity | (id: string | null) => Promise<void> | Set or clear user identity |
refresh | () => Promise<void> | Manually refresh feature flags |
getFeatureValue | (key: string) => boolean | Get raw feature value |
Examples
Conditional Rendering
function CheckoutButton() {
const { isEnabled: useNewCheckout, isLoading } = useFeatureFlag('new-checkout');
if (isLoading) {
return <ActivityIndicator />;
}
return useNewCheckout ? (
<NewCheckoutButton onPress={handleNewCheckout} />
) : (
<ClassicCheckoutButton onPress={handleClassicCheckout} />
);
}
Combined Feature Gates
function PremiumContent() {
const { isEnabled: hasPremiumAccess } = useFeatureGate(
['premium-subscription', 'beta-tester'],
{ requirement: 'any' } // User has premium OR is beta tester
);
if (!hasPremiumAccess) {
return <UpgradePrompt />;
}
return <PremiumContentView />;
}
User Login/Logout
function AuthButtons() {
const { setIdentity, refresh } = useToggly();
const [user, setUser] = useState(null);
const handleLogin = async (credentials) => {
const userData = await loginAPI(credentials);
setUser(userData);
// Set identity for targeted feature rollouts
await setIdentity(userData.id);
};
const handleLogout = async () => {
await logoutAPI();
setUser(null);
// Clear identity
await setIdentity(null);
};
return (
<View>
{user ? (
<Button title="Logout" onPress={handleLogout} />
) : (
<Button title="Login" onPress={() => handleLogin(credentials)} />
)}
</View>
);
}
Manual Refresh
function SettingsScreen() {
const { refresh } = useToggly();
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = async () => {
setRefreshing(true);
try {
await refresh();
} finally {
setRefreshing(false);
}
};
return (
<ScrollView
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} />
}
>
{/* Content */}
</ScrollView>
);
}
Entity context
Pass the entity into useFeatureFlag / useToggly().isFeatureOn per call. Do not put entity attributes on setIdentity. See Entity & page context.
const { enabled } = useFeatureFlag('OrderBadge', { context: order, contextKind: 'Order' })
Clients register mappers locally only. Missing context fails closed.
Best Practices
- Use
useFeatureFlagfor single flags - It's optimized for single feature checks - Use
useFeatureGatefor multiple flags - When you need AND/OR logic - Use
useTogglyfor advanced operations - Identity management, manual refresh - Handle loading states - Show appropriate UI while flags are loading
- Provide defaults - Use
featureDefaultsfor offline scenarios