---
title: React Native Feature Flags
description: Set up Datadog Feature Flags for React Native applications.
breadcrumbs: Docs > Feature Flags > Client-Side Feature Flags > React Native Feature Flags
---

# React Native Feature Flags

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ().
{% /alert %}

{% /callout %}

## Overview{% #overview %}

This page describes how to instrument your React Native application with the Datadog Feature Flags SDK. Datadog feature flags provide a unified way to remotely control feature availability in your app, experiment safely, and deliver new experiences with confidence.

The Datadog Feature Flags SDK for React Native is built on [OpenFeature](https://openfeature.dev/), an open standard for feature flag management. This guide explains how to install the SDK, configure the Datadog provider, and evaluate flags in your React Native components.

## Requirements{% #requirements %}

- **React Native** version 0.65 or later
- **iOS** version 13 or later
- **Android** API level 23 or later
- **Datadog React Native SDK** (`@datadog/mobile-react-native`) must be initialized first

## Installation{% #installation %}

Install the Datadog React Native SDK, the OpenFeature provider, and the OpenFeature React SDK using your preferred package manager:

{% tab title="npm" %}

```bash
npm install @datadog/mobile-react-native @datadog/mobile-react-native-openfeature @openfeature/react-sdk @openfeature/web-sdk @openfeature/core
```

{% /tab %}

{% tab title="yarn" %}

```bash
yarn add @datadog/mobile-react-native @datadog/mobile-react-native-openfeature @openfeature/react-sdk @openfeature/web-sdk @openfeature/core
```

{% /tab %}

### iOS setup{% #ios-setup %}

Install the added pod:

```bash
(cd ios && pod install)
```

### Android setup{% #android-setup %}

If you use React Native version 0.68 or higher, use Java 17. If you use React Native version 0.67 or lower, use Java version 11.

In your `android/build.gradle` file, specify the `kotlinVersion` to avoid clashes among Kotlin dependencies:

In the `build.gradle` file:

```groovy
buildscript {
    ext {
        kotlinVersion = "1.8.21"
    }
}
```

## Initialize the SDK{% #initialize-the-sdk %}

The Datadog OpenFeature provider for React Native requires the core Datadog SDK to be initialized first, followed by enabling the Feature Flags feature.

### Option 1: Using DatadogProvider component{% #option-1-using-datadogprovider-component %}

If you use the `DatadogProvider` component for SDK initialization, enable Feature Flags in the `onInitialized` callback:

```tsx
import { DatadogProvider, DatadogProviderConfiguration, DdFlags } from '@datadog/mobile-react-native';
import { DatadogOpenFeatureProvider } from '@datadog/mobile-react-native-openfeature';
import { OpenFeature, OpenFeatureProvider } from '@openfeature/react-sdk';

const config = new DatadogProviderConfiguration(
    '<CLIENT_TOKEN>',
    '<ENVIRONMENT_NAME>',
    trackingConsent,
    {
      rumConfiguration: {
        applicationId: '<APPLICATION_ID>',
      },
      // ...
    },
);
config.site = '<YOUR_DATADOG_SITE>';

export default function App() {
    return (
        <DatadogProvider
            configuration={config}
            onInitialized={async () => {
                await DdFlags.enable();

                const provider = new DatadogOpenFeatureProvider();
                OpenFeature.setProvider(provider);
            }}
        >
            <OpenFeatureProvider>
                <Navigation />
            </OpenFeatureProvider>
        </DatadogProvider>
    );
}
```

### Option 2: Using imperative initialization{% #option-2-using-imperative-initialization %}

If you initialize the SDK imperatively, enable Feature Flags after initialization completes:

```tsx
import { DdSdkReactNative, DdFlags, CoreConfiguration } from '@datadog/mobile-react-native';
import { DatadogOpenFeatureProvider } from '@datadog/mobile-react-native-openfeature';
import { OpenFeature } from '@openfeature/react-sdk';

(async () => {
    const config = new CoreConfiguration(
        '<CLIENT_TOKEN>',
        '<ENVIRONMENT_NAME>',
        '<APPLICATION_ID>'
    );
    config.site = '<YOUR_DATADOG_SITE>';

    await DdSdkReactNative.initialize(config);

    // Enable Feature Flags after core SDK initialization
    await DdFlags.enable();

    // Set the Datadog provider with OpenFeature
    const provider = new DatadogOpenFeatureProvider();
    OpenFeature.setProvider(provider);
})();
```

{% alert level="info" %}
Sending flag evaluation data to Datadog is automatically enabled when using the Feature Flags SDK. Provide `rumIntegrationEnabled` and `trackExposures` parameters to the `DdFlags.enable()` call to configure this behavior.
{% /alert %}

## Set the evaluation context{% #set-the-evaluation-context %}

Define who or what the flag evaluation applies to using an evaluation context. The evaluation context includes user or session information used to determine which flag variations should be returned. Reference these attributes in your targeting rules to control who sees each variant.

```javascript
import { OpenFeature } from '@openfeature/react-sdk';

const evaluationContext = {
  targetingKey: 'user-123',
  user_id: '123',
  email: 'user@example.com',
  tier: 'premium',
};

OpenFeature.setContext(evaluationContext);
```

{% alert level="info" %}
The `targetingKey` is used as the randomization subject for percentage-based targeting. When a flag targets a percentage of subjects (for example, 50%), the `targetingKey` determines which "bucket" a user falls into. Users with the same `targetingKey` always receive the same variant for a given flag.
{% /alert %}

## Wrap your application{% #wrap-your-application %}

Wrap your application with the `OpenFeatureProvider` component. This makes feature flags available to all child components through React context.

```tsx
import { OpenFeatureProvider } from '@openfeature/react-sdk';

function App() {
    return (
        <OpenFeatureProvider>
            <YourApp />
        </OpenFeatureProvider>
    );
}
```

## Evaluate flags{% #evaluate-flags %}

The OpenFeature React SDK provides hooks for evaluating flags within your components. Each hook returns the flag value based on the evaluation context you configured. Flag evaluation is *local and instantaneous*—the SDK uses locally cached data, so no network requests occur when evaluating flags.

### Boolean flags{% #boolean-flags %}

Use `useBooleanFlagValue(key, defaultValue)` for flags that represent on/off or true/false conditions:

```jsx
import { useBooleanFlagValue } from '@openfeature/react-sdk';

function CheckoutButton() {
  const isNewCheckoutEnabled = useBooleanFlagValue('new_checkout_button', false);

  if (isNewCheckoutEnabled) {
    return <NewCheckoutButton />;
  }

  return <LegacyCheckoutButton />;
}
```

### String flags{% #string-flags %}

Use `useStringFlagValue(key, defaultValue)` for flags that select between multiple variants or configuration strings:

```jsx
import { useStringFlagValue } from '@openfeature/react-sdk';

function ThemedComponent() {
  const theme = useStringFlagValue('ui_theme', 'light');

  switch (theme) {
    case 'dark':
      return <DarkTheme />;
    case 'light':
    default:
      return <LightTheme />;
  }
}
```

### Number flags{% #number-flags %}

Use `useNumberFlagValue(key, defaultValue)` for numeric flags such as limits, percentages, or multipliers:

```jsx
import { useNumberFlagValue } from '@openfeature/react-sdk';

function CartDisplay() {
  const maxItems = useNumberFlagValue('max_cart_items', 20);

  return <Cart maxItems={maxItems} />;
}
```

### Object flags{% #object-flags %}

Use `useObjectFlagValue(key, defaultValue)` for structured configuration data:

```jsx
import { useObjectFlagValue } from '@openfeature/react-sdk';

function Banner() {
  const config = useObjectFlagValue('promo_banner', {
    color: '#00A3FF',
    message: 'Welcome!',
  });

  return <PromoBanner color={config.color} message={config.message} />;
}
```

### Suspense support{% #suspense-support %}

Built-in [suspense](https://react.dev/reference/react/Suspense) support allows you to avoid displaying components with feature flags until provider initialization is complete, or when the context changes. Pass `{ suspend: true }` in the hook options to use this functionality.

For example:

```jsx
import { useBooleanFlagValue } from '@openfeature/react-sdk';
import { Suspense } from 'react';

function Content() {
  // Display a loading message if the component uses feature flags and the provider is not ready
  return (
    <Suspense fallback={"Loading..."}>
      <WelcomeMessage />
    </Suspense>
  );
}

function WelcomeMessage() {
  const { value: showNewMessage } = useBooleanFlagValue('show-new-welcome-message', false, { suspend: true });

  return (
    <>
      {showNewMessage ? (
        <p>Welcome! You're seeing the new experience.</p>
      ) : (
        <p>Welcome back!</p>
      )}
    </>
  );
}
```

### Flag evaluation details{% #flag-evaluation-details %}

When you need more than just the flag value, use the detail hooks. These return both the evaluated value and metadata explaining the evaluation:

- `useBooleanFlagDetails(key, defaultValue)`
- `useStringFlagDetails(key, defaultValue)`
- `useNumberFlagDetails(key, defaultValue)`
- `useObjectFlagDetails(key, defaultValue)`

For example:

```jsx
import { useStringFlagDetails } from '@openfeature/react-sdk';

function PaywallLayout() {
  const details = useStringFlagDetails('paywall_layout', 'control');

  console.log(details.value);   // Evaluated value (for example: "A", "B", or "control")
  console.log(details.variant); // Variant name, if applicable
  console.log(details.reason);  // Description of why this value was chosen

  return <Layout variant={details.value} />;
}
```

Flag details help you debug evaluation behavior and understand why a user received a given value.

## Complete example{% #complete-example %}

Here's a complete example showing how to set up and use Datadog Feature Flags in a React Native application:

```tsx
import { Suspense } from 'react';
import { View } from 'react-native';
import { DatadogProvider, DatadogProviderConfiguration, DdFlags } from '@datadog/mobile-react-native';
import { DatadogOpenFeatureProvider } from '@datadog/mobile-react-native-openfeature';
import { OpenFeature, OpenFeatureProvider, useBooleanFlagValue } from '@openfeature/react-sdk';

const config = new DatadogProviderConfiguration(
    '<CLIENT_TOKEN>',
    '<ENVIRONMENT_NAME>',
    trackingConsent,
    {
      rumConfiguration: {
        applicationId: '<APPLICATION_ID>',
      },
      // ...
    },
);

// Wrap your app with the DatadogProvider and OpenFeatureProvider.
export default function AppWithProviders() {
    // Based on your auth state.
    const user = getCurrentUser();

    return (
        <DatadogProvider
            configuration={config}
            onInitialized={async () => {
                await DdFlags.enable();

                const provider = new DatadogOpenFeatureProvider();

                const evaluationContext = {
                    targetingKey: user.id,
                    region: user.country,
                };

                OpenFeature.setProvider(provider, evaluationContext);
            }}
        >
          <Suspense fallback={<Loading />}>
            <OpenFeatureProvider suspendUntilReady>
                <App />
            </OpenFeatureProvider>
          </Suspense>
        </DatadogProvider>
    );
}

// Use feature flags in your components
function App() {
    const showNewFeature = useBooleanFlagValue('new_feature', false);

    return (
        <View>
            {showNewFeature ? <NewFeature /> : <ExistingFeature />}
        </View>
    );
}
```

## Update the evaluation context{% #update-the-evaluation-context %}

To update the evaluation context after initialization (for example, when a user logs in), use `OpenFeature.setContext()`:

```tsx
import { OpenFeature } from '@openfeature/react-sdk';

// When a user logs in
function onUserLogin(user) {
    OpenFeature.setContext({
        targetingKey: user.id,
        email: user.email,
        plan: user.plan,
    });
}
```

## Configure Feature Flags options{% #configure-feature-flags-options %}

Pass configuration options to `DdFlags.enable()` to customize Feature Flags behavior:

```tsx
await DdFlags.enable({
    // Send flag evaluation data to RUM for session analysis (default: true)
    rumIntegrationEnabled: true,
    // Track flag exposures for analytics (default: true)
    trackExposures: true,
});
```

{% dl %}

{% dt %}
`rumIntegrationEnabled`
{% /dt %}

{% dd %}
When `true` (default), flag evaluations are tracked in RUM, which enables correlating them with user sessions. This enables analytics such as *"Do users in variant B experience more errors?"*.
{% /dd %}

{% dt %}
`trackExposures`
{% /dt %}

{% dd %}
When `true` (default), the SDK automatically records an *exposure event* when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can analyze feature adoption.
{% /dd %}

{% /dl %}

## Context attribute requirements{% #context-attribute-requirements %}

{% alert level="warning" %}
Evaluation context attributes must be flat primitive values (strings, numbers, Booleans). Nested objects and arrays are **not supported** and will be dropped from the evaluation context.
{% /alert %}

Use flat attributes in your evaluation context:

```javascript
OpenFeature.setContext({
    targetingKey: 'user-123',
    userId: 'user-123',
    tier: 'premium',
    age: 25
});
```

Avoid nested objects and arrays:

```javascript
// These attributes will be dropped from the evaluation context with a console warning.
OpenFeature.setContext({
    targetingKey: 'user-123',
    user: { id: 'user-123' },        // nested object - NOT SUPPORTED
    features: ['beta', 'analytics']  // array - NOT SUPPORTED
});
```

## Troubleshooting{% #troubleshooting %}

### No flags returned{% #no-flags-returned %}

If flag evaluations return default values:

1. Verify the Datadog SDK is initialized before calling `DdFlags.enable()`.
1. Confirm `DdFlags.enable()` completed before setting the OpenFeature provider.
1. Check that the evaluation context is set before evaluating flags.
1. Confirm the flag exists and is enabled in your Datadog Feature Flags dashboard.

### iOS pod install errors{% #ios-pod-install-errors %}

If you have `use_frameworks!` enabled in your `Podfile`, you may see errors during `pod install`. Edit your `Podfile` to install the SDK pod as a static library:

In the `Podfile` file:

```ruby
static_libraries = ['DatadogSDKReactNative']

pre_install do |installer|
  installer.pod_targets.each do |pod|
    if static_libraries.include?(pod.name)
      def pod.static_framework?;
        true
      end
      def pod.build_type;
        Pod::BuildType.static_library
      end
    end
  end
end
```

### Feature Flags not initialized error{% #feature-flags-not-initialized-error %}

If you see an error about Feature Flags not being initialized, verify the initialization order:

1. Initialize the core Datadog SDK first (`DdSdkReactNative.initialize()` or `DatadogProvider`).
1. Call `DdFlags.enable()` after SDK initialization.
1. Create and set the `DatadogOpenFeatureProvider` after enabling flags.

## Further reading{% #further-reading %}

- [OpenFeature React SDK](https://openfeature.dev/docs/reference/sdks/client/web/react/)
- [Client-Side Feature Flags](https://docs.datadoghq.com/feature_flags/client.md)
- [React Native Monitoring](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/react_native.md)
