
## Set up the SDK

{% steps %}
{% step title="Install the SDK" %}
## Installation

Statsig uses a multi-package strategy. Install both the Statsig client and the React Native specific bindings.

{% codetabs %}
```shell NPM
npm install @statsig/react-native-bindings
```

```shell Yarn
yarn add @statsig/react-native-bindings
```
{% /codetabs %}

### Peer Dependencies

The `@statsig/react-native-bindings` package has peer dependencies which may also need to be installed if they aren't already in your project.

{% codetabs %}
```shell NPM
npm install react-native-device-info @react-native-async-storage/async-storage
```

```shell Yarn
yarn add react-native-device-info @react-native-async-storage/async-storage
```
{% /codetabs %}
{% /step %}

{% step title="Initialize the SDK" %}
Next, initialize the SDK with a client SDK key from the ["API Keys" tab on the Statsig console](https://console.statsig.com/api_keys). These keys are safe to embed in a client application.

Along with the key, pass in a [User Object](#statsig-user) with the attributes you'd like to target later on in a gate or experiment.

## React Native + React Specific Setup

The setup for a ReactNative environment is very similar to a plain [React environment](/client/React).
The only difference is that you need to use the ReactNative specific `StatsigProviderRN`.
This automatically switches out the storage layer used by the SDK, utilizing [AsyncStorage](https://github.com/react-native-async-storage) instead of LocalStorage (which isn't available in RN environments).

```tsx
import {
  StatsigProviderRN,
  useFeatureGate,
} from "@statsig/react-native-bindings";

function Content() {
  const gate = useFeatureGate("a_gate");

  // Reason: Network or NetworkNotModified
  return (
    <View>
      <Text>Value: {gate.value ? "Pass" : "Fail"}</Text>
      <Text>Reason: {gate.details.reason}</Text>
    </View>
  );
}

function App() {
  return (
    <StatsigProviderRN
      sdkKey={YOUR_CLIENT_KEY}
      user={{ userID: "a-user" }}
      loadingComponent={<Text>Loading...</Text>}
    >
      <Content />
    </StatsigProviderRN>
  );
}
```
{% /step %}
{% /steps %}

## Use the SDK

Get an instance of the StatsigClient to check gates, experiments, dynamic configs, layers, and log events.

```jsx
import { useStatsigClient } from "@statsig/react-native-bindings";

const { client } = useStatsigClient();
```

The available methods are listed in the sections below.

### Checking a Feature Flag/Gate

Now that your SDK is initialized, let's check a [**Feature Gate**](/feature-flags/overview). Feature Gates can be used to create logic branches in code that can be rolled out to different users from the Statsig Console. Gates are always **CLOSED** or **OFF** (think `return false;`) by default.

You can evaluate a gate by getting the client with the `useStatsigClient` hook, and then calling `checkGate`

```tsx
const { client } = useStatsigClient();
return (
  <div>Gate is {client.checkGate('check_user') ? 'passing' : 'failing'}.</div>
);
```

### Reading a Dynamic Config

Feature Gates are useful for simple on/off switches with optional advanced user targeting. To send a different set of values (strings, numbers, etc.) to clients based on specific user attributes such as country, use **Dynamic Configs**. The API is similar to Feature Gates, but you get a complete JSON object you can configure on the server and fetch typed parameters from it. For example:

You can get a DynamicConfig value by getting the client with the `useStatsigClient` hook, and then calling `getConfig`

```tsx
const { client } = useStatsigClient();
const config = client.getConfig('app_properties');

return (
  <div>{config.get('title', 'Default Title')}</div>
);
```

### Getting a Layer/Experiment

**Layers/Experiments** let you run A/B/n experiments. Two APIs are available, but Statsig recommends [layers](/experiments/layers-overview) for quicker iterations with parameter reuse.

You can access the experiment variant and parameters for the user by getting the client with the `useStatsigClient` hook, and then calling `getExperiment`.

```tsx
const { client } = useStatsigClient();
const experiment = client.getExperiment('headline_test');

return (
  <div>Headline Parameter: {experiment.get('headline', 'Default')}.</div>
);
```

You can access layers and layer parameters for the user by getting the client with the `useStatsigClient` hook, and then calling `getLayer`.

```tsx
const { client } = useStatsigClient();
const layer = client.getLayer('homepage_layer');

return (
  <div>Headline Parameter: {layer.get('hero_text', 'Welcome')}.</div>
);
```

### Logging an Event

After setting up a Feature Gate or Experiment, you may want to track custom events to see how new features or different experiment groups affect those events. Call the Log Event API for the event. You can also provide a value and metadata object to be logged with the event.

Get the client with the `useStatsigClient` hook, then call `logEvent`:

```tsx
const { client } = useStatsigClient();
return <button onClick={() => client.logEvent("button_click")}>Click Me</button>
```

### Flushing Logged Events

`flush()` sends queued events immediately. Use `shutdown()` when your app is exiting.

```tsx
import { Button } from 'react-native';
import { useStatsigClient } from '@statsig/react-native-bindings';

const { client } = useStatsigClient();

return (
  <Button
    title="Flush Events"
    onPress={async () => {
      await client.flush();
    }}
  />
);
```

## Loading State

Depending on your setup, you may want to wait for the latest values before checking a gate or experiment. If you are using `StatsigProviderRN`, pass in a `loadingComponent` prop to display a loading state while the SDK initializes. If you are using the `useClientAsyncInitRN` hook, check the `isLoading` prop to determine if the SDK is still loading.

{% tabs %}
{% tab title="StatsigProviderRN" %}
```tsx
export function App() {
  const loadingComponent = <div>Loading...</div>;

  return (
    <StatsigProviderRN
      ...
      loadingComponent={loadingComponent} // <- Pass in the loading component
    >
        <YourComponent />
    </StatsigProviderRN>
  );
}
```
{% /tab %}

{% tab title="useClientAsyncInitRN" %}
```tsx
export function App() {
  const { client, isLoading } = useClientAsyncInitRN(...);

  if (isLoading) {
    return <div>Loading...</div>;
  }

  return (
    <StatsigProviderRN client={client}>
      <YourComponent />
    </StatsigProviderRN>
  );
}
```
{% /tab %}
{% /tabs %}

## Lifecycle & Advanced Usage

## Shutting Statsig Down

The SDK keeps event logs in the client cache and flushes them periodically to save data and battery usage. Because of this, the SDK may not have flushed some events when your app shuts down.

To ensure all logged events are flushed or saved locally, shut down Statsig when your app is closing:

```tsx
import { useEffect } from 'react';
import { useStatsigClient } from '@statsig/react-native-bindings';

const { client } = useStatsigClient();

useEffect(() => {
  return () => {
    void client.shutdown();
  };
}, [client]);
```

## Advanced

### StatsigClient Outside the Component Tree

In some scenarios, you may need to use the `StatsigClient` outside the React component tree. For example, in background tasks or notification handlers, use the RN-specific `StatsigClientRN`.

```tsx
import { StatsigClientRN } from '@statsig/react-native-bindings';

const myClient = new StatsigClientRN(
  YOUR_CLIENT_KEY,
  { userID: "a-user" }
);

await myClient.initializeAsync();

if (myClient.checkGate("my_gate")) {
  // do something cool
}
```

To access the StatsigClient instance created by the StatsigProvider outside the component tree, use the `StatsigClientRN.instance()` method. This returns the first StatsigClient instance created. If you have multiple instances, pass in the SDK key to get a specific instance.

```tsx
// Inside the component tree
function App() {
  return <StatsigProviderRN sdkKey={YOUR_CLIENT_KEY} user={{ userID: "a-user" }}>
    <Text>...</Text>
  </StatsigProviderRN>
}

// Outside the component tree
const client = StatsigClientRN.instance(); // get the first created instance

const client = StatsigClientRN.instance(YOUR_CLIENT_KEY); // get a specific instance by SDK key
```

### Synchronous Storage with MMKV

Because LocalStorage is unavailable in React Native environments, the SDK prefetches all Statsig cache entries during initialization by default.

If you are using MMKV in your project and prefer it over the default (AsyncStorage), provide your own `StorageProvider` through `StatsigOptions`.

```tsx
import { MMKV } from "react-native-mmkv";
import { StorageProvider } from "@statsig/client-core";
import { StatsigProviderRN } from '@statsig/react-native-bindings';

function App() {
    const [storageProvider] = useState<StorageProvider>(() => {
      const mmkv = new MMKV();

      return {
        isReady: () => true,
        isReadyResolver: () => null,
        getProviderName: () => "MMKV",
        getAllKeys: () => mmkv.getAllKeys(),
        getItem: (key: string) => mmkv.getString(key) ?? null,
        setItem: (key: string, value: string) => mmkv.set(key, value),
        removeItem: (key: string) => mmkv.delete(key),
      };
    });

   return (
    <StatsigProviderRN
      sdkKey={YOUR_CLIENT_KEY}
      user={{ userID: "a-user" }}
      options={{
        storageProvider, // <- Passed into StatsigOptions
      }}
    >
      <Text>...</Text>
    </StatsigProviderRN>
   );
}
```
