Skip to main content

React SDK Usage

Learn how to integrate Superflag into your React web application.

Setup Provider

Wrap your app with SuperflagProvider at the root level:
// app/layout.tsx
import { SuperflagProvider } from '@superflag-sh/react'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <SuperflagProvider clientKey={process.env.NEXT_PUBLIC_SUPERFLAG_CLIENT_KEY}>
          {children}
        </SuperflagProvider>
      </body>
    </html>
  )
}

Using Flags

Basic Usage

Use the useFlag hook to access flag values:
import { useFlag } from '@superflag-sh/react'

function MyComponent() {
  const showNewFeature = useFlag('new-feature', false)

  return (
    <div>
      {showNewFeature && <NewFeatureUI />}
    </div>
  )
}

Type-Safe Flags

Use TypeScript generics for type-safe flag values:
import { useFlag } from '@superflag-sh/react'

function ThemeSelector() {
  // Boolean flag
  const darkMode = useFlag<boolean>('dark-mode', false)

  // String flag
  const theme = useFlag<string>('theme', 'light')

  // Number flag
  const maxItems = useFlag<number>('max-items', 10)

  // JSON flag
  const config = useFlag<{ color: string; size: number }>('ui-config', {
    color: 'blue',
    size: 14
  })

  return <div style={{ color: config.color }}>Theme: {theme}</div>
}

Checking SDK Status

Use useFlags to check if the SDK is ready:
import { useFlags } from '@superflag-sh/react'

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

  if (loading) {
    return <div>Loading flags...</div>
  }

  if (error) {
    return <div>Error: {error}</div>
  }

  if (!ready) {
    return <div>Initializing...</div>
  }

  return <div>Flags loaded!</div>
}

Provider Props

Configure the provider with these optional props:
PropTypeDefaultDescription
clientKeystringenv varPublic client key (pub_*)
ttlSecondsnumber60Cache time-to-live in seconds
storageStorageAdapterlocalStorageCustom storage adapter

Custom TTL

Control how long flags are cached:
// Cache for 5 minutes
<SuperflagProvider clientKey="pub_..." ttlSeconds={300}>
  <App />
</SuperflagProvider>

Custom Storage

Provide a custom storage adapter for specialized use cases:
import { SuperflagProvider } from '@superflag-sh/react'

const customStorage = {
  async getItem(key: string): Promise<string | null> {
    return sessionStorage.getItem(key)
  },
  async setItem(key: string, value: string): Promise<void> {
    sessionStorage.setItem(key, value)
  },
  async removeItem(key: string): Promise<void> {
    sessionStorage.removeItem(key)
  }
}

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

Caching Behavior

The SDK uses smart ETag-based caching to minimize bandwidth:
  1. First load: Fetches flags from API, stores in localStorage
  2. Subsequent loads:
    • Shows cached flags immediately
    • Checks for updates in background using ETag
    • Only downloads if config changed (HTTP 304 if unchanged)
  3. Cache expiry: After ttlSeconds, forces a fresh fetch
This means your app loads instantly with cached flags while staying up-to-date in the background.

Environment Variables

Next.js

.env.local
NEXT_PUBLIC_SUPERFLAG_CLIENT_KEY=pub_prod_...

Vite

.env
VITE_SUPERFLAG_CLIENT_KEY=pub_prod_...

Create React App

.env
REACT_APP_SUPERFLAG_CLIENT_KEY=pub_prod_...
Always use public keys (pub_*) in client-side code. Never use SDK keys (sdk_*).

Status Values

The status field from useFlags() can be:
StatusDescription
idleInitial state before fetching
loadingFetching flags from API
readyFlags loaded successfully
errorFailed to load flags
rate-limitedMonthly quota exceeded

Error Handling

The SDK never crashes your app. Errors are returned in the state:
function MyComponent() {
  const { status, error } = useFlags()

  if (status === 'error') {
    console.error('Failed to load flags:', error)
    // App continues with fallback values
  }

  if (status === 'rate-limited') {
    console.warn('Rate limited - using cached flags')
  }

  // Your component code...
}

Next Steps