> ## Documentation Index
> Fetch the complete documentation index at: https://superflag.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage

> Learn how to use feature flags in your React Native and Expo app

# React Native SDK Usage

Learn how to integrate Superflag into your React Native or Expo application.

## Setup Provider

Wrap your app with `SuperflagProvider` at the root level:

<Tabs>
  <Tab title="Expo">
    ```tsx App.tsx theme={null}
    import { SuperflagProvider } from '@superflag-sh/react-native'

    export default function App() {
      return (
        <SuperflagProvider clientKey={process.env.EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY}>
          <YourApp />
        </SuperflagProvider>
      )
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```tsx App.tsx theme={null}
    import { SuperflagProvider } from '@superflag-sh/react-native'

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

    export default App
    ```
  </Tab>
</Tabs>

## Using Flags

### Basic Usage

Use the `useFlag` hook to access flag values:

```tsx theme={null}
import { useFlag } from '@superflag-sh/react-native'
import { View, Text } from 'react-native'

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

  return (
    <View>
      {showNewFeature && <NewFeatureComponent />}
    </View>
  )
}
```

### Type-Safe Flags

Use TypeScript generics for type-safe flag values:

```tsx theme={null}
import { useFlag } from '@superflag-sh/react-native'

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

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

  // Number flag
  const fontSize = useFlag<number>('font-size', 16)

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

  return (
    <Text style={{ color: config.color, fontSize: config.size }}>
      Theme: {theme}
    </Text>
  )
}
```

### Checking SDK Status

Use `useFlags` to check if the SDK is ready:

```tsx theme={null}
import { useFlags } from '@superflag-sh/react-native'
import { ActivityIndicator, View, Text } from 'react-native'

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

  if (loading) {
    return <ActivityIndicator />
  }

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

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

  return <YourContent />
}
```

## Provider Props

Configure the provider with these optional props:

| Prop         | Type     | Default | Description                   |
| ------------ | -------- | ------- | ----------------------------- |
| `clientKey`  | `string` | env var | Public client key (`pub_*`)   |
| `ttlSeconds` | `number` | `60`    | Cache time-to-live in seconds |

### Custom TTL

Control how long flags are cached:

```tsx theme={null}
// Cache for 5 minutes
<SuperflagProvider clientKey="pub_..." ttlSeconds={300}>
  <App />
</SuperflagProvider>
```

## Caching Behavior

The SDK uses AsyncStorage for persistent caching:

1. **First launch**: Fetches flags from API, stores in AsyncStorage
2. **Subsequent launches**:
   * 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.

## Environment Variables

### Expo

```bash .env theme={null}
EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY=pub_prod_...
```

Then access in your code:

```tsx theme={null}
<SuperflagProvider clientKey={process.env.EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY}>
```

### React Native with react-native-config

1. Install `react-native-config`:
   ```bash theme={null}
   npm install react-native-config
   ```

2. Create `.env` file:
   ```bash .env theme={null}
   SUPERFLAG_CLIENT_KEY=pub_prod_...
   ```

3. Use in code:
   ```tsx theme={null}
   import Config from 'react-native-config'

   <SuperflagProvider clientKey={Config.SUPERFLAG_CLIENT_KEY}>
   ```

<Warning>
  Always use **public keys** (`pub_*`) in mobile apps. Never use server keys (`sdk_*`).
</Warning>

## Status Values

The `status` field from `useFlags()` can be:

| Status         | Description                   |
| -------------- | ----------------------------- |
| `idle`         | Initial state before fetching |
| `loading`      | Fetching flags from API       |
| `ready`        | Flags loaded successfully     |
| `error`        | Failed to load flags          |
| `rate-limited` | Monthly quota exceeded        |

## Error Handling

The SDK never crashes your app. Errors are returned in the state:

```tsx theme={null}
function MyScreen() {
  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...
}
```

## Offline Support

The SDK works offline using cached flags:

```tsx theme={null}
import { useFlag, useFlags } from '@superflag-sh/react-native'
import NetInfo from '@react-native-community/netinfo'

function MyScreen() {
  const [isOnline, setIsOnline] = useState(true)
  const feature = useFlag('feature', false)
  const { lastFetchedAt } = useFlags()

  useEffect(() => {
    const unsubscribe = NetInfo.addEventListener(state => {
      setIsOnline(state.isConnected ?? false)
    })
    return unsubscribe
  }, [])

  return (
    <View>
      {!isOnline && <Text>Offline mode - using cached flags</Text>}
      {feature && <FeatureComponent />}
    </View>
  )
}
```

## Performance Tips

### Avoid Re-renders

```tsx theme={null}
import { memo } from 'react'
import { useFlag } from '@superflag-sh/react-native'

const ExpensiveComponent = memo(function ExpensiveComponent() {
  const config = useFlag('config', { items: 10 })

  // This only re-renders when config actually changes
  return <HeavyList items={config.items} />
})
```

### Conditional Rendering

```tsx theme={null}
function OptionalFeature() {
  const enabled = useFlag('optional-feature', false)

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

  return <ExpensiveFeatureComponent />
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/react-native/api-reference">
    Complete type definitions and API docs
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/react-native/troubleshooting">
    Common issues and solutions
  </Card>
</CardGroup>
