Skip to main content

React SDK Examples

Common patterns and real-world examples for using Superflag in your React application.

Feature Toggles

Simple Boolean Flag

import { useFlag } from '@superflag-sh/react'

function FeatureComponent() {
  const showNewUI = useFlag('new-ui', false)

  return showNewUI ? <NewUI /> : <LegacyUI />
}

Gradual Rollout

import { useFlag } from '@superflag-sh/react'

function Dashboard() {
  const betaFeaturesEnabled = useFlag('beta-features', false)

  return (
    <div>
      <StandardDashboard />
      {betaFeaturesEnabled && (
        <BetaFeatures />
      )}
    </div>
  )
}

Configuration

Theme Configuration

import { useFlag } from '@superflag-sh/react'

interface ThemeConfig {
  primaryColor: string
  borderRadius: number
  fontFamily: string
}

function App() {
  const theme = useFlag<ThemeConfig>('theme-config', {
    primaryColor: '#3B82F6',
    borderRadius: 8,
    fontFamily: 'Inter'
  })

  return (
    <div style={{
      '--primary': theme.primaryColor,
      '--radius': `${theme.borderRadius}px`,
      fontFamily: theme.fontFamily
    }}>
      <YourApp />
    </div>
  )
}

API Endpoints

import { useFlag } from '@superflag-sh/react'

function DataFetcher() {
  const apiUrl = useFlag<string>('api-base-url', 'https://api.example.com')

  useEffect(() => {
    fetch(`${apiUrl}/data`)
      .then(res => res.json())
      .then(setData)
  }, [apiUrl])

  return <DataDisplay data={data} />
}

Loading States

Show Loading Spinner

import { useFlags } from '@superflag-sh/react'

function App() {
  const { loading } = useFlags()

  if (loading) {
    return <LoadingSpinner />
  }

  return <YourApp />
}

Skeleton While Loading

import { useFlags, useFlag } from '@superflag-sh/react'

function FeatureCard() {
  const { ready } = useFlags()
  const enabled = useFlag('card-feature', false)

  if (!ready) {
    return <CardSkeleton />
  }

  return enabled ? <EnhancedCard /> : <BasicCard />
}

Error Handling

Graceful Degradation

import { useFlags } from '@superflag-sh/react'

function MyComponent() {
  const { status, error } = useFlags()

  if (status === 'error') {
    console.error('Failed to load feature flags:', error)
    // Continue with defaults
  }

  if (status === 'rate-limited') {
    // Show warning but don't block
    console.warn('Rate limited - using cached flags')
  }

  // Component works with fallback values
  return <YourComponent />
}

Error Boundary

import { useFlags } from '@superflag-sh/react'

function FlagStatusMonitor() {
  const { status, error } = useFlags()

  if (status === 'error') {
    return (
      <Alert variant="warning">
        Feature flags unavailable. Using defaults. {error}
      </Alert>
    )
  }

  return null
}

function App() {
  return (
    <>
      <FlagStatusMonitor />
      <YourApp />
    </>
  )
}

Performance Optimization

Memoization

import { useFlag } from '@superflag-sh/react'
import { useMemo } from 'react'

function ExpensiveComponent() {
  const config = useFlag<{ items: number }>('config', { items: 100 })

  const processedData = useMemo(() => {
    return expensiveComputation(config.items)
  }, [config.items])

  return <Display data={processedData} />
}

Conditional Rendering

import { useFlag } from '@superflag-sh/react'

function OptionalFeature() {
  const enabled = useFlag('optional-feature', false)

  // Early return to avoid rendering
  if (!enabled) return null

  return <ExpensiveFeatureComponent />
}

Custom Storage

Session Storage

import { SuperflagProvider, type StorageAdapter } from '@superflag-sh/react'

const sessionStorage: StorageAdapter = {
  async getItem(key) {
    return window.sessionStorage.getItem(key)
  },
  async setItem(key, value) {
    window.sessionStorage.setItem(key, value)
  },
  async removeItem(key) {
    window.sessionStorage.removeItem(key)
  }
}

function App() {
  return (
    <SuperflagProvider clientKey="pub_..." storage={sessionStorage}>
      <YourApp />
    </SuperflagProvider>
  )
}

IndexedDB Storage

import { SuperflagProvider, type StorageAdapter } from '@superflag-sh/react'

const indexedDBStorage: StorageAdapter = {
  async getItem(key) {
    const db = await openDB()
    return db.get('superflag', key)
  },
  async setItem(key, value) {
    const db = await openDB()
    await db.put('superflag', value, key)
  },
  async removeItem(key) {
    const db = await openDB()
    await db.delete('superflag', key)
  }
}

function App() {
  return (
    <SuperflagProvider clientKey="pub_..." storage={indexedDBStorage}>
      <YourApp />
    </SuperflagProvider>
  )
}

Environment-Specific Flags

Development vs Production

import { useFlag } from '@superflag-sh/react'

function DevTools() {
  const isDev = process.env.NODE_ENV === 'development'
  const devToolsEnabled = useFlag('dev-tools', isDev)

  if (!devToolsEnabled) return null

  return <DeveloperToolsPanel />
}

Multi-Environment Setup

// app/layout.tsx
import { SuperflagProvider } from '@superflag-sh/react'

function getClientKey() {
  const env = process.env.NODE_ENV

  if (env === 'production') {
    return process.env.NEXT_PUBLIC_SUPERFLAG_PROD_KEY!
  }
  if (env === 'staging') {
    return process.env.NEXT_PUBLIC_SUPERFLAG_STAGING_KEY!
  }
  return process.env.NEXT_PUBLIC_SUPERFLAG_DEV_KEY!
}

export default function RootLayout({ children }) {
  return (
    <SuperflagProvider clientKey={getClientKey()}>
      {children}
    </SuperflagProvider>
  )
}

Next Steps