React
Full API reference for @signakit/flags-react — SignaKitProvider, useFlag hook, and FlagGate component for client-side feature flags in React applications.
React SDK
Package: @signakit/flags-react
Peer dependency: @signakit/flags-browser
Registry: npm
Environments: React 18+, browser
A thin wrapper around @signakit/flags-browser that provides a context provider, a useFlag hook, and a declarative FlagGate component. Handles initialization, loading state, and makes flag decisions available anywhere in the component tree.
Next.js App Router? Evaluate flags in server components using @signakit/flags-node — no React SDK needed. See the Next.js App Router guide →
Installation
npm install @signakit/flags-react @signakit/flags-browserSignaKitProvider
Wrap your application root with SignaKitProvider. It initializes the browser SDK, fetches the config, and makes all flag decisions available via hooks and FlagGate.
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { SignaKitProvider } from '@signakit/flags-react'
import App from './App'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<SignaKitProvider
sdkKey="sk_prod_yourOrgId_yourProjectId_random"
userId="user-123"
attributes={{ plan: 'pro', country: 'US' }}
loadingFallback={<div>Loading…</div>}
>
<App />
</SignaKitProvider>
</StrictMode>
)Props
| Prop | Type | Required | Description |
|---|---|---|---|
sdkKey | string | ✓ | Your SignaKit browser SDK key |
userId | string | ✓ | Stable unique identifier for the current user. Changes trigger re-evaluation of all flags. |
attributes | Record<string, string | number | boolean> | — | User attributes matched against targeting rules |
loadingFallback | ReactNode | — | Rendered while the config is fetching. If omitted, children render immediately with loading: true from useFlag. |
timeout | number | — | Config fetch timeout in ms (default: 5000) |
onError | (reason: string) => void | — | Called when config fetch fails after all retries |
Memoize attributes to avoid unnecessary re-evaluation
// ❌ New object on every render → re-evaluates all flags
<SignaKitProvider attributes={{ plan: user.plan }}>
// ✓ Stable reference
const attributes = useMemo(() => ({ plan: user.plan }), [user.plan])
<SignaKitProvider attributes={attributes}>useFlag(flagKey)
Evaluates a single flag for the current user.
import { useFlag } from '@signakit/flags-react'
function CheckoutButton() {
const { enabled, variationKey, loading } = useFlag('new-checkout')
if (loading) return <Skeleton />
return enabled ? <NewCheckoutButton /> : <LegacyCheckoutButton />
}Return value
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether the flag is on. false while loading. |
variationKey | string | null | Assigned variation key. null while loading or flag off/not found. |
ruleKey | string | null | Matched rule key. |
loading | boolean | true until the Provider finishes fetching config. Always false when loadingFallback is set on the Provider. |
FlagGate
Declarative show/hide based on a flag.
import { FlagGate } from '@signakit/flags-react'
function FeaturePage() {
return (
<>
{/* Show when flag is enabled */}
<FlagGate flag="new-sidebar">
<NewSidebar />
</FlagGate>
{/* Show specific variation, fallback for others */}
<FlagGate flag="checkout-redesign" variation="treatment" fallback={<LegacyCheckout />}>
<NewCheckout />
</FlagGate>
</>
)
}Props
| Prop | Type | Required | Description |
|---|---|---|---|
flag | string | ✓ | Flag key to evaluate |
variation | string | — | If provided, children only render when the user is in this specific variation |
fallback | ReactNode | — | Rendered when the flag is off, user doesn't match, or variation doesn't match |
useFlagAll()
Returns all flag decisions for the current user.
import { useFlagAll } from '@signakit/flags-react'
function Dashboard() {
const { decisions, loading } = useFlagAll()
if (loading) return <Skeleton />
return (
<>
{decisions['new-sidebar']?.enabled && <NewSidebar />}
{decisions['beta-analytics']?.enabled && <BetaAnalytics />}
</>
)
}useFlagAll() fires an $exposure event for every flag the user is bucketed into. Use useFlag() for single flags.
useTrackEvent()
Returns a track(eventName, properties?) function bound to the current user context.
import { useTrackEvent } from '@signakit/flags-react'
function PurchaseButton({ amount }: { amount: number }) {
const track = useTrackEvent()
return (
<button onClick={() => track('purchase_completed', { value: amount })}>
Buy now
</button>
)
}Fire and forget — never throws.
SSR and hydration
The React SDK is client-only. In Next.js App Router, mark files using it with 'use client'.
To avoid hydration mismatches when rendering flag-gated content:
- Recommended: Evaluate in a server component, pass as a prop — no Provider needed.
- Render flag-gated content only after
loading: falsefromuseFlag(). - Set
loadingFallbackon the Provider and wrap with aSuspenseboundary.
Anti-patterns
| Pattern | Problem | Fix |
|---|---|---|
Calling decide() directly on the browser client in a component | Bypasses Provider dedup and loading state | Use useFlag() |
Inline attributes object on the Provider | New object every render → re-evaluates all flags | Memoize with useMemo |
| Using the React SDK in a Next.js server component | Hooks and browser APIs can't run server-side | Use @signakit/flags-node in server components |
Rendering flag-gated content before loading: false | Flashes wrong variant during config fetch | Check loading or use loadingFallback |
Related
Last updated on
Browser
Full API reference for @signakit/flags-browser — client-side feature flags with CDN-fetched config, local evaluation, and sessionStorage exposure deduplication.
React Native
Full API reference for @signakit/flags-react-native — SignaKitProvider, useFlag hook, and AsyncStorage config persistence for feature flags in React Native and Expo apps.