Flagdeck
Pricing
Docs
Get Started

Docs

Docs


SDKs

  • JavaScript
    • Getting Started
    • Value Types
    • Evaluation Context
    • Configuration
    • Real Time Updates
    • Error Handling
    • Middleware
    • Offline Mode
    • API Reference
  • React
  • Vue

API Reference

  • Authentication
  • Flags
  • Environments
  • Projects

React SDK

The Flagdeck React SDK provides an easy way to use feature flags in React applications. Built on top of the JavaScript SDK, it offers React-specific components and hooks for a more idiomatic integration with your React projects.

Installation

Install the React SDK using npm, yarn, or pnpm:

# Using npm
npm install @flagdeck/react

# Using yarn
yarn add @flagdeck/react

# Using pnpm
pnpm add @flagdeck/react

The SDK automatically installs the Flagdeck JavaScript SDK as a dependency.

Quick Start

Wrap your application with the FlagdeckProvider and start using the hooks and components:

import React from 'react';
import { FlagdeckProvider, useFlag } from '@flagdeck/react';

function App() {
  return (
    <FlagdeckProvider 
      options={{ 
        apiKey: 'YOUR_API_KEY',
        realTimeUpdates: true,
      }}
    >
      <YourApp />
    </FlagdeckProvider>
  );
}

function YourApp() {
  const { isEnabled, isLoading } = useFlag('new-feature');
  
  if (isLoading) return <div>Loading...</div>;
  
  return (
    <div>
      {isEnabled ? 'New feature is enabled!' : 'New feature is disabled'}
    </div>
  );
}

Provider Setup

FlagdeckProvider

The FlagdeckProvider initializes the Flagdeck SDK and provides the client instance to all child components.

<FlagdeckProvider
  options={{
    apiKey: 'your-api-key',             // Required
    debug: true,                        // Optional: enables debug logging
    realTimeUpdates: true,              // Optional: enables real-time flag updates via SSE
    timeout: 5000,                      // Optional: API request timeout in ms
    enableCache: true,                  // Optional: enables caching of flag evaluations
    cacheTimeout: 30000,                // Optional: cache TTL in ms
    enableOfflineMode: false,           // Optional: enables offline fallback
    enableAnalytics: true,              // Optional: enables analytics tracking
  }}
  initialContext={{                 // Optional: initial user context
    userId: 'user-123',                 // User identifier
    attributes: {                       // User attributes for targeting
      country: 'US',
      plan: 'premium'
    }
  }}
  readyDelayMs={100}                    // Optional: delay before marking SDK as ready
>
  {children}
</FlagdeckProvider>

Hooks

useFlagdeck

Access the Flagdeck client and context:

import { useFlagdeck } from '@flagdeck/react';

function UserSettings() {
  const { 
    client,               // Flagdeck client instance
    isReady,              // True when SDK is initialized and ready
    error,                // Error object if SDK initialization failed
    context,          // Current user context
    setContext        // Function to update user context
  } = useFlagdeck();
  
  // Update user context based on selections
  const handlePlanChange = (plan) => {
    setContext({
      ...context,
      attributes: {
        ...context?.attributes,
        plan
      }
    });
  };
  
  return (
    <div>
      {!isReady && <div>Loading SDK...</div>}
      {error && <div>Error: {error.message}</div>}
      {isReady && (
        <select 
          value={context?.attributes?.plan || 'free'} 
          onChange={(e) => handlePlanChange(e.target.value)}
        >
          <option value="free">Free Plan</option>
          <option value="premium">Premium Plan</option>
        </select>
      )}
    </div>
  );
}

useFlag

Evaluate a boolean feature flag:

import { useFlag } from '@flagdeck/react';

function FeatureComponent() {
  const { 
    isEnabled,            // Boolean flag value
    isLoading,            // True when flag is being evaluated
    error                 // Error object if evaluation failed
  } = useFlag('new-dashboard', false);  // 'false' is the default value
  
  if (isLoading) return <div>Loading...</div>;
  
  if (error) {
    console.warn(`Flag error: ${error.message}`);
    // Continue with default value
  }
  
  return (
    <div>
      {isEnabled ? <NewDashboard /> : <LegacyDashboard />}
    </div>
  );
}

useFlagValue

Get a feature flag value of any type:

import { useFlagValue } from '@flagdeck/react';

function ThemeComponent() {
  const { 
    value: theme,         // Flag value (can be any type)
    isLoading,            // True when flag is being evaluated
    error                 // Error object if evaluation failed
  } = useFlagValue('theme-variant', 'default');  // 'default' is the default value
  
  // Apply different styles based on theme value
  const themeStyles = {
    default: { background: 'white', color: 'black' },
    dark: { background: 'black', color: 'white' },
    blue: { background: '#0070F3', color: 'white' }
  };
  
  const style = themeStyles[theme] || themeStyles.default;
  
  return (
    <div style={style}>
      Current theme: {isLoading ? 'Loading...' : theme}
    </div>
  );
}

useFlags

Evaluate multiple flags at once:

import { useFlags } from '@flagdeck/react';

function FeatureDashboard() {
  const { 
    values,               // Record of flag keys to their values
    isLoading,            // True when flags are being evaluated
    errors                // Record of flag keys to error objects
  } = useFlags(['new-header', 'sidebar', 'analytics'], false);
  
  if (isLoading) return <div>Loading features...</div>;
  
  // Count enabled features
  const enabledCount = Object.values(values).filter(Boolean).length;
  
  return (
    <div>
      <p>Enabled features: {enabledCount}/{Object.keys(values).length}</p>
      
      {values['new-header'] && <NewHeader />}
      {values['sidebar'] && <Sidebar />}
      {values['analytics'] && <AnalyticsPanel />}
      
      {/* Example of handling errors */}
      {Object.entries(errors).map(([key, error]) => (
        <div key={key} className="error">
          Error with {key}: {error.message}
        </div>
      ))}
    </div>
  );
}

Components

FeatureFlag

Conditionally render content based on flag state:

import { FeatureFlag } from '@flagdeck/react';

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      
      <FeatureFlag
        flagKey="new-dashboard"
        defaultEnabled={false}
        fallback={<LegacyDashboard />}
        loadingContent={<div>Loading dashboard...</div>}
        onError={(error) => console.error('Dashboard flag error:', error)}
      >
        <NewDashboard />
      </FeatureFlag>
    </div>
  );
}

FlagValue

Render prop component for accessing flag values:

import { FlagValue } from '@flagdeck/react';

function ThemeWrapper({ children }) {
  return (
    <FlagValue flagKey="color-theme" defaultValue="default">
      {({ value: theme, isLoading }) => {
        // Apply theme classes or styles based on the theme value
        const themeClass = `theme-${isLoading ? 'default' : theme}`;
        
        return (
          <div className={themeClass}>
            {isLoading && <div className="theme-loading-indicator" />}
            {children}
          </div>
        );
      }}
    </FlagValue>
  );
}

WithFeature

Render prop alternative for conditional rendering:

import { WithFeature } from '@flagdeck/react';

function PaymentOptions() {
  return (
    <div>
      <h2>Payment Options</h2>
      
      {/* Always shown payment methods */}
      <CreditCardOption />
      <PayPalOption />
      
      {/* Conditionally shown new payment methods */}
      <WithFeature flagKey="crypto-payments">
        {({ isEnabled, isLoading }) => (
          <>
            {isLoading && <div>Loading payment options...</div>}
            {isEnabled && <CryptoPaymentOption />}
          </>
        )}
      </WithFeature>
    </div>
  );
}

Real-time Flag Updates

The React SDK supports real-time updates via Server-Sent Events (SSE). When enabled, flag changes made in the Flagdeck dashboard will be pushed to your application immediately without requiring page refreshes.

<FlagdeckProvider
  options={{
    apiKey: 'your-api-key',
    realTimeUpdates: true  // Enable real-time updates
  }}
>
  <App />
</FlagdeckProvider>

Then in your components, the hooks will automatically update with new values when flags change:

function FeatureMonitor() {
  const { isEnabled } = useFlag('monitored-feature');
  
  // This will automatically re-render when the flag changes
  return (
    <div>
      Feature status: {isEnabled ? 'Enabled' : 'Disabled'}
    </div>
  );
}

User Targeting

Set or update user context to target features to specific users:

function UserProfile() {
  const { context, setContext } = useFlagdeck();
  
  const handlePlanChange = (plan) => {
    setContext({
      ...context,
      attributes: {
        ...context?.attributes,
        plan
      }
    });
  };
  
  return (
    <div>
      <h2>User Profile</h2>
      <select 
        value={context?.attributes?.plan || 'free'}
        onChange={(e) => handlePlanChange(e.target.value)}
      >
        <option value="free">Free Plan</option>
        <option value="pro">Pro Plan</option>
        <option value="enterprise">Enterprise Plan</option>
      </select>
      
      {/* This component will re-evaluate flags when user context changes */}
      <FeaturePanel />
    </div>
  );
}

Error Handling

All hooks provide error information that you can use to handle different error scenarios:

function FeatureSection() {
  const { isEnabled, error } = useFlag('beta-feature');

  // Handle different error types
  if (error) {
    switch (error.type) {
      case 'notfound':
        return <div>This feature is not configured yet.</div>;
      
      case 'inactive':
        return <div>This feature is currently disabled.</div>;
      
      case 'configuration':
        return <div>There's a configuration issue with this feature.</div>;
      
      default:
        return <div>Error loading feature: {error.message}</div>;
    }
  }

  // Normal rendering when no errors
  return (
    <div>
      {isEnabled ? (
        <div>Beta feature is enabled!</div>
      ) : (
        <div>Beta feature is disabled.</div>
      )}
    </div>
  );
}

Advanced Patterns

Feature-gated Routing

import { useFlag } from '@flagdeck/react';
import { Navigate, Route } from 'react-router-dom';

function ProtectedFeatureRoute({ 
  flagKey, 
  fallbackPath = '/access-denied', 
  children 
}) {
  const { isEnabled, isLoading } = useFlag(flagKey);
  
  if (isLoading) {
    return <div>Loading access...</div>;
  }
  
  return isEnabled ? children : <Navigate to={fallbackPath} />;
}

// Usage in routes
function AppRoutes() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route 
        path="/beta-feature" 
        element={
          <ProtectedFeatureRoute flagKey="beta-access">
            <BetaFeature />
          </ProtectedFeatureRoute>
        } 
      />
    </Routes>
  );
}

Lazy Loading with Feature Flags

import React, { lazy, Suspense } from 'react';
import { useFlag } from '@flagdeck/react';

// Define components
const LegacyComponent = lazy(() => import('./LegacyComponent'));
const NewComponent = lazy(() => import('./NewComponent'));

function FeatureWithLazyLoad() {
  const { isEnabled, isLoading } = useFlag('new-component');
  
  if (isLoading) {
    return <div>Loading feature flags...</div>;
  }
  
  // Choose which component to render based on flag
  const Component = isEnabled ? NewComponent : LegacyComponent;
  
  return (
    <Suspense fallback={<div>Loading component...</div>}>
      <Component />
    </Suspense>
  );
}

Theme System with Feature Flags

import { createContext, useContext } from 'react';
import { useFlagValue } from '@flagdeck/react';

// Create theme context
const ThemeContext = createContext({
  theme: 'default',
  isDark: false
});

function ThemeProvider({ children }) {
  const { value: theme } = useFlagValue('app-boot-theme', 'default');
  
  // Calculate theme properties
  const themeData = {
    theme,
    isDark: theme === 'dark' || theme === 'midnight',
    // Other theme properties...
  };
  
  useEffect(() => {
    // Apply theme to document root
    document.documentElement.setAttribute('data-theme', theme);
    
    if (themeData.isDark) {
      document.documentElement.classList.add('dark-mode');
    } else {
      document.documentElement.classList.remove('dark-mode');
    }
  }, [theme, themeData.isDark]);
  
  return (
    <ThemeContext.Provider value={themeData}>
      {children}
    </ThemeContext.Provider>
  );
}

// Hook to use theme
const useTheme = () => useContext(ThemeContext);

TypeScript Support

The React SDK is built with TypeScript and provides full type definitions:

import { useFlag, useFlagValue } from '@flagdeck/react';

function TypedComponent() {
  // Boolean flag
  const { isEnabled } = useFlag('feature-flag');
  
  // String flag with specific type
  const { value: theme } = useFlagValue<'light' | 'dark' | 'system'>('theme', 'system');
  
  // Number flag
  const { value: limit } = useFlagValue<number>('rate-limit', 100);
  
  // Complex object flag
  interface ConfigType {
    timeout: number;
    retries: number;
    endpoints: string[];
  }
  
  const defaultConfig: ConfigType = {
    timeout: 3000,
    retries: 3,
    endpoints: ['api.example.com']
  };
  
  const { value: config } = useFlagValue<ConfigType>('api-config', defaultConfig);
  
  return (
    <div>
      <p>Feature enabled: {String(isEnabled)}</p>
      <p>Theme: {theme}</p>
      <p>Rate limit: {limit}</p>
      <p>API timeout: {config.timeout}ms</p>
    </div>
  );
}

Best Practices

  1. Initialize Early: Place FlagdeckProvider high in your component tree to make flags available throughout your app.

  2. Handle Loading States: Always check isLoading before using flag values to avoid flash of incorrect content.

  3. Provide Default Values: Always specify default values that make sense for your application as fallbacks.

  4. Use Error Boundaries: Wrap flag-dependent components in error boundaries to catch evaluation errors.

  5. Batch Flag Evaluations: Use useFlags to evaluate multiple flags at once for better performance.

  6. Consider Server-Side Rendering: For SSR apps, provide sensible defaults and revalidate flags on the client side.

  7. Keep User Context Updated: Always update user context when user attributes change to ensure correct targeting.

  8. Cache Key Flags: Consider saving critical flags to local storage for offline use.

Performance Considerations

  • Minimize Re-renders: Use the useFlagdeck hook only in components that need to access or update the user context.

  • Optimize Flag Access: Use useFlags for multiple flags instead of multiple useFlag calls.

  • Enable Caching: Keep the default caching enabled to reduce API calls.

  • Use Real-time Updates Wisely: Only enable real-time updates for flags that need immediate propagation.

Next Steps

For more detailed information about the underlying JavaScript SDK features and configuration options, refer to the JavaScript SDK documentation.

Start using Flagdeck today

Simple feature flag management for modern development teams.

Get Started
Flagdeck

Modern feature flag management platform to help you deploy with confidence.

Product

FeaturesPricingDocumentation

© 2025 Flagdeck. All rights reserved.