@featureflip/react
React bindings for Featureflip feature flag evaluation.
Installation
npm install @featureflip/react @featureflip/browser
Quick Start
Wrap your app with FeatureflipProvider, then use useFeatureFlag in any component.
import { FeatureflipProvider, useFeatureFlag } from '@featureflip/react';
function App() {
return (
<FeatureflipProvider clientKey="your-client-sdk-key">
<Banner />
</FeatureflipProvider>
);
}
function Banner() {
const showBanner = useFeatureFlag('show-banner', false);
if (!showBanner) return null;
return <div>New feature available!</div>;
}
Provider Props
| Prop | Type | Default | Description |
|---|---|---|---|
clientKey | string | (required) | Client SDK key |
context | Record<string, unknown> | undefined | Evaluation context (user attributes) |
baseUrl | string | undefined | Evaluation API base URL |
streaming | boolean | undefined | Enable SSE streaming |
sendEvaluationEvents | boolean | true | Passed to the browser SDK; see its README. |
bootstrap | Record<string, unknown> | 'localStorage' | undefined | Values to render before the first server response. Passed to the browser SDK; see its README. |
The provider creates a FeatureflipClient internally and calls initialize() on mount. It cleans up (calls close()) on unmount.
With a bootstrap object (for example, flag values your server evaluated while rendering the page), useFeatureFlag returns those values on the first render and useFeatureflipStatus() reports isReady: true immediately; the server's values replace them when they arrive. During server rendering the provider uses FeatureflipClient.forServerRender, which serves only the bootstrap values, makes no requests, and is not shared between requests.
Hooks
useFeatureFlag<T>(key: string, defaultValue: T): T
Returns the evaluated value of a flag. The component re-renders automatically when the flag value changes via streaming or identify(). The type of defaultValue determines which variation method is called (boolVariation, stringVariation, numberVariation, or jsonVariation).
const enabled = useFeatureFlag('new-checkout', false);
const color = useFeatureFlag('button-color', 'blue');
const limit = useFeatureFlag('rate-limit', 100);
const config = useFeatureFlag('ui-config', { sidebar: true });
useFeatureflipStatus(): { isReady, isError, error }
Returns the initialization status of the client. Useful for showing loading states.
function App() {
const { isReady, isError, error } = useFeatureflipStatus();
if (isError) return <div>Error: {error?.message}</div>;
if (!isReady) return <div>Loading...</div>;
return <Main />;
}
useFeatureflipClient(): FeatureflipClient
Returns the underlying FeatureflipClient instance for direct access (e.g., calling identify).
Identify on Login
When the context prop changes, the provider automatically calls identify() and re-evaluates all flags. You can also call identify directly.
function LoginPage() {
const client = useFeatureflipClient();
async function handleLogin(userId: string) {
// ... authenticate ...
await client.identify({ user_id: userId, plan: 'pro' });
}
return <button onClick={() => handleLogin('123')}>Log in</button>;
}
Testing
Use TestFeatureflipProvider to supply predetermined flag values in tests -- no network calls, no initialization delay.
import { TestFeatureflipProvider } from '@featureflip/react';
import { render, screen } from '@testing-library/react';
test('renders banner when flag is on', () => {
render(
<TestFeatureflipProvider flags={{ 'show-banner': true }}>
<Banner />
</TestFeatureflipProvider>,
);
expect(screen.getByText('New feature available!')).toBeInTheDocument();
});
TestFeatureflipProvider uses FeatureflipClient.forTesting() internally and sets isReady: true immediately.
License
Apache-2.0