React
Use Flipswitch feature flags in React with hooks and real-time updates
The OpenFeature React SDK provides React-specific hooks and components on top of the Flipswitch web provider. Flags evaluate client-side and re-render automatically when values change via SSE.
See the JavaScript SDK for full provider configuration (polling fallback, offline support, etc.).
Installation
npm install @flipswitch-io/web-provider @openfeature/react-sdkyarn add @flipswitch-io/web-provider @openfeature/react-sdkpnpm add @flipswitch-io/web-provider @openfeature/react-sdk@openfeature/react-sdk re-exports everything from @openfeature/web-sdk, so you do not need to install it separately.
Quick Start
import { OpenFeatureProvider, OpenFeature, useFlag } from '@openfeature/react-sdk';
import { FlipswitchWebProvider } from '@flipswitch-io/web-provider';
// Initialize once at app startup
OpenFeature.setProvider(
new FlipswitchWebProvider({ apiKey: 'YOUR_API_KEY' })
);
function App() {
return (
<OpenFeatureProvider>
<MyComponent />
</OpenFeatureProvider>
);
}
function MyComponent() {
const { value: darkMode } = useFlag('dark-mode', false);
return (
<div className={darkMode ? 'dark' : 'light'}>
Dark mode is {darkMode ? 'enabled' : 'disabled'}
</div>
);
}useFlag Hook
useFlag infers the flag type from the default value and returns a query object:
const { value, reason, variant, isError, errorMessage } = useFlag('flag-key', defaultValue);Works with all flag types:
const { value: enabled } = useFlag('new-feature', false); // boolean
const { value: greeting } = useFlag('welcome-message', 'Hello!'); // string
const { value: limit } = useFlag('max-items', 10); // number
const { value: config } = useFlag('ui-config', { theme: 'light' }); // objectTyped Hooks
If you prefer explicit typing, use the type-specific hooks:
import {
useBooleanFlagValue,
useBooleanFlagDetails,
useStringFlagValue,
useNumberFlagValue,
useObjectFlagValue,
} from '@openfeature/react-sdk';
const darkMode = useBooleanFlagValue('dark-mode', false);
const details = useBooleanFlagDetails('dark-mode', false);
// details.value, details.variant, details.reasonReal-Time Updates
The useFlag hook automatically re-renders when flag values change via SSE. No additional setup is needed beyond enabling real-time updates on the provider (enabled by default).
function Banner() {
// This component re-renders whenever 'promo-banner' changes in Flipswitch
const { value: showBanner } = useFlag('promo-banner', false);
if (!showBanner) return null;
return <div className="banner">Special offer!</div>;
}Re-renders are triggered by the Flipswitch provider emitting PROVIDER_CONFIGURATION_CHANGED events when it receives SSE updates.
Evaluation Context
Set user context for targeting rules. Context can be set globally or updated from within components:
Global Context
import { OpenFeature } from '@openfeature/react-sdk';
// Set context before or after provider initialization
OpenFeature.setContext({
targetingKey: 'user-123',
email: 'user@example.com',
plan: 'premium',
});Context Mutator Hook
Update context from within components using useContextMutator:
import { useContextMutator } from '@openfeature/react-sdk';
function UserProfile({ user }) {
const { setContext } = useContextMutator();
useEffect(() => {
setContext({
targetingKey: user.id,
email: user.email,
plan: user.plan,
});
}, [user]);
return <FeatureEnabledContent />;
}Suspense Support
Suspend rendering until the provider is ready, avoiding flashes of default values:
import { useSuspenseFlag } from '@openfeature/react-sdk';
import { Suspense } from 'react';
function Feature() {
const { value: enabled } = useSuspenseFlag('new-feature', false);
return enabled ? <NewFeature /> : <OldFeature />;
}
function App() {
return (
<OpenFeatureProvider>
<Suspense fallback={<Loading />}>
<Feature />
</Suspense>
</OpenFeatureProvider>
);
}You can also enable suspense selectively on useFlag:
const { value } = useFlag('my-flag', false, { suspend: true });FeatureFlag Component
For declarative conditional rendering without hooks:
import { FeatureFlag } from '@openfeature/react-sdk';
function Page() {
return (
<FeatureFlag flagKey="dark-mode" defaultValue={false} fallback={<LightTheme />}>
<DarkTheme />
</FeatureFlag>
);
}With a render function for access to the evaluated value:
<FeatureFlag flagKey="welcome-message" defaultValue="Hello!">
{({ value }) => <h1>{value}</h1>}
</FeatureFlag>Domain-Scoped Providers
Use separate providers for different parts of your app:
OpenFeature.setProvider('checkout', new FlipswitchWebProvider({ apiKey: 'CHECKOUT_KEY' }));
function CheckoutPage() {
return (
<OpenFeatureProvider domain="checkout">
<CheckoutFeatures />
</OpenFeatureProvider>
);
}Next.js
In Next.js App Router, the provider setup must happen in a Client Component:
'use client';
import { OpenFeatureProvider, OpenFeature } from '@openfeature/react-sdk';
import { FlipswitchWebProvider } from '@flipswitch-io/web-provider';
OpenFeature.setProvider(
new FlipswitchWebProvider({ apiKey: 'YOUR_API_KEY' })
);
export function FeatureFlagProvider({ children }: { children: React.ReactNode }) {
return <OpenFeatureProvider>{children}</OpenFeatureProvider>;
}Then use in your layout:
import { FeatureFlagProvider } from './feature-flag-provider';
export default function RootLayout({ children }) {
return (
<html>
<body>
<FeatureFlagProvider>{children}</FeatureFlagProvider>
</body>
</html>
);
}Testing
Use OpenFeatureTestProvider for deterministic flag values in tests:
import { OpenFeatureTestProvider } from '@openfeature/react-sdk';
import { render } from '@testing-library/react';
render(
<OpenFeatureTestProvider flagValueMap={{ 'dark-mode': true, 'max-items': 25 }}>
<MyComponent />
</OpenFeatureTestProvider>
);