Overview
The @flagsync/react-sdk integrates into React applications for client-side feature management and event tracking—ideal for single-user contexts like browser environments.
Requires React 16.3+ due to its dependency on the React Context API.
Installation
Install the SDK with your preferred package manager:
npm install @flagsync/react-sdk
npm install -D @flagsync/cli
Quickstart
A basic example of using the SDK in a React application:
import { useFlag , FlagSyncProvider } from '@flagsync/react-sdk' ;
function MyApp () {
return (
< FlagSyncProvider config = { {
sdkKey: 'your-sdk-key' ,
core: {
key: 'user-123'
}
} } >
< MyComponent />
</ FlagSyncProvider >
);
}
function MyComponent () {
const { value , isReady , isReadyFromStore } = useFlag ( 'my-first-kill-switch' , false );
if ( ! isReady ) {
return < div > Loading... </ div > ;
}
return < div > Feature is { value ? 'enabled' : 'disabled' } </ div > ;
}
Initialization
Get Your SDK Key
Find your client-side SDK key in your workspace settings —safe for web/mobile apps (keep server-side keys private).
Initialize the SDK
Wrap your application with FlagSyncProvider and provide the required configuration:
import { FlagSyncProvider } from '@flagsync/react-sdk' ;
function App () {
return (
< FlagSyncProvider
config = { {
sdkKey: 'your-sdk-key' ,
core: {
key: 'user-123'
}
// other configuration options...
} }
>
{ /* Your app components */ }
</ FlagSyncProvider >
);
}
Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.
Wait for Readiness
Prevent flickering by ensuring the SDK is ready before your app renders.
Use the waitForReady prop in FlagSyncProvider to delay rendering until the SDK is initialized, or check readiness manually with hooks or render prop components:
Using waitForReady
Add waitForReady to FlagSyncProvider to delay rendering until the SDK is ready, avoiding flicker during initialization. < FlagSyncProvider waitForReady config = { config } >
< MyApp />
</ FlagSyncProvider >
Using hooks or render prop components
Check isReady with hooks like useFlag, useFlags, or useFlagSyncClient to control rendering useFlag
useFlags
useFlagSyncClient
const { isReady , isReadyFromStore } = useFlag ( 'my-first-kill-switch' , false );
Identical properties are provided in <FlagSyncFlag />, and <FlagSyncFlags />.
SDK Not Ready
If the SDK isn’t ready, it returns the defaultValue or control:
// value: false (defaultValue) isReady: false
const { value , isReady } = useFlag ( 'flag-one' , false );
// value: "control", isReady: false
const { value , isReady } = useFlag ( 'flag-two' );
SDK Ready
Once ready, hooks return the server-evaluated value:
// value: Server-evaluated value, isReady: true
const { value , isReady } = useFlag ( 'flag-one' );
Client-side SDKs can bootstrap via LocalStorage or an initial flag set—values apply until the SDK is ready.
See Flag Evaluation: Overview .
Usage
Evaluate Flags
Evaluates a feature flag for user context. Applies targeting rules, rollouts, and defaults values.
// Get a single flag value
const { value } = useFlag ( 'my-first-kill-switch' , defaultValue );
FlagSync CLI
When using the CLI, flag values are automatically inferred from the generated types:
useFlag ( 'layout' ); // Type: 'v1' | 'v2' | 'v3'
useFlag ( 'killswitch' ); // Type: boolean
useFlag ( 'price-discount' ); // Type: 0.1 | 0.2
useFlag ( 'price-discount' , 0.5 ); // ❌ TS Error: Invalid default value
useFlag ( 'invalid-flag' ); // ❌ TS Error: Invalid flag key
Without generated types, you must manually specify the type:
useFlag < 'v1' | 'v2' >( 'layout' ); // Type: 'v1' | 'v2'
useFlag < number >( 'price-discount' ); // Type: number
useFlag < boolean >( 'enable-feature' , false ); // Type: boolean (defaultValue must be true or false)
useFlag ( 'no-type' ) // Type: unknown
An Impression is automatically logged either of the flag hooks are called.
Track Events
Submit user actions with the useTrack hook, which supports two usage patterns:
With a pre-filled event key
Bind the hook to a specific event key for repeated tracking: const track = useTrack ( 'page-visit' ); // Bound to eventKey
useEffect (() => track ())
With a dynamic event key
Use a generic track function to specify the event key at call time: const track = useTrack ();
< Button onClick = { () => {
track ( 'purchase-event' , null , { productId: 'prod-123' })
} } >
Buy Now
</ Button >
SDK Event Listeners
The SDK emits these events for SDK lifecycle management:
SDK_UPDATE: Emitted when flags are updated
SDK_READY: Emitted when the SDK is ready
SDK_READY_FROM_STORE: Emitted when flags are loaded from storage
ERROR: Emitted when an error occurs during initialization
Access these events using the useFlagSyncClient hook:
import { useFlagSyncClient } from '@flagsync/react-sdk'
const client = useFlagSyncClient ();
useEffect (() => {
const onUpdate = () => {
console . log ( 'Flags updated:' , client . lastUpdated );
};
client . on ( 'SDK_UPDATE' , onUpdate );
return () => client . off ( 'SDK_UPDATE' , onUpdate );
}, [ client ]);
SDK_UPDATE does not fire if syncing is disabled.
Configuration
Configure the SDK with the FsConfig interface:
interface FsConfig {
sdkKey : string ; // Required: Your SDK key
core : {
key : string ; // Required: User identifier
attributes ?: Record < string , any >; // Optional: Custom user attributes
};
bootstrap ?: Record < string , any >; // Optional: Initial flag values
storage ?: {
type ?: 'memory' | 'localstorage' ; // Optional: Storage type
prefix ?: string ; // Optional: Storage key prefix
};
sync ?: {
type ?: 'stream' | 'poll' | 'off' ; // Optional: Sync strategy
pollRate ?: number ; // Optional: Polling interval in seconds
};
tracking ?: {
impressions ?: {
maxQueueSize : number ; // Required: Max impressions queue size
pushRate : number ; // Required: Impressions push rate
};
events ?: {
maxQueueSize : number ; // Required: Max events queue size
pushRate : number ; // Required: Events push rate
};
};
urls ?: {
sdk ?: string ; // Optional: SDK endpoint URL
};
logger ?: Partial < ILogger >; // Optional: Custom logger
logLevel ?: LogLevel ; // Optional: Logging level
metadata ?: Record < string , any >; // Optional: Additional metadata
}
Custom Attributes
Define user attributes for targeting in Flags: User Segments .
< FlagSyncProvider
config = { {
sdkKey: 'your-sdk-key' ,
core: {
key: 'user-123' ,
attributes: {
plan: 'premium' ,
country: 'US' ,
userType: 'enterprise'
}
}
} }
>
{ /* Your app */ }
</ FlagSyncProvider >
Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.
Flag Syncing
Configure flag update strategies with the sync object: stream, poll, or off.
By default, flag updates propagate in milliseconds via server-side events (SSE), ensuring the latest values are used in evaluations.
Components using flag hooks re-render automatically—no event listeners needed.
To disable this behavior, set sync to off, requiring a page refresh to fetch updated flags.
Stream (Default)
Stream updates via SSE—flag updates are reevaluated on the server and sent to the client: const config : FsConfig = {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'stream'
}
};
Polling
Poll the server on an interval: const config : FsConfig = {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'poll' ,
pollRate: 60
}
};
Off
Disable syncing: const config : FsConfig = {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'off'
}
};
Bootstrapping
Initialize the SDK with a set of bootstrap flags:
< FlagSyncProvider
config = { {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
bootstrap: {
'feature-1' : true ,
'feature-2' : false
}
} }
>
{ /* Your app */ }
</ FlagSyncProvider >
Storage
Choose between memory and LocalStorage storage types:
Memory (Default)
const config : FsConfig = {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
storage: {
type: 'memory'
}
};
LocalStorage
const config : FsConfig = {
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
storage: {
type: 'localstorage'
prefix : 'flagsync' // Optional: Custom prefix for storage keys
}
};
Use the useFlagSyncClient to get the client.isReadyFromStore property.
Best Practices
Use isReady checks to handle loading states. See Wait for Readiness .
Select a sync strategy (stream/poll/off) based on your application’s needs.
Use useTrack for consistent event tracking in components.
Add user attributes for targeted feature rollouts.
Consider bootstrapping for faster initial renders.
Environment Variables
Set the following environment variable:
FLAGSYNC_SDK_KEY: Your client-side FlagSync SDK key (required)