Skip to main content

Statsig in Expo

💡 Tip: Get started quickly with one of our sample apps!

Installation​

To use Statsig in Expo, you will need to install the Statsig Expo specific bindings.

npx expo install @statsig/expo-bindings

Peer Dependencies​

The @statsig/expo-bindings package has peer dependencies which may also need to be installed if they are not already in your project.

npx expo install expo-device expo-application @react-native-async-storage/async-storage

Expo + React Specific Setup​

The setup for an Expo environment is very similar to a plain React environment. The only difference is that you need to use the Expo specific StatsigProviderExpo. This automatically switches out the storage layer used by the SDK, utilizing AsyncStorage instead of LocalStorage (which isn't available in RN environments).

import { StatsigProviderExpo, useFeatureGate } from "@statsig/expo-bindings";

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

return <Text>Reason: {gate.details.reason}</Text>; // Reason: Network or NetworkNotModified
}

function App() {
return (
<StatsigProviderExpo
sdkKey={YOUR_CLIENT_KEY}
user={{ userID: "a-user" }}
options={{ environment: { tier: "development" } }} // (Optional)
loadingComponent={<Text>Loading...</Text>}
>
<Content />
</StatsigProviderExpo>
);
}
caution

Avoid iOS 18.4 on Simulator: Apple introduced a networking bug in iOS 18.4 that causes requests to fail when running in the Simulator. For more details, see this thread on Apple's forums.

The Basics​

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

import { useStatsigClient } from "@statsig/expo-bindings";

const { client } = useStatsigClient();

See the methods you can call on the client below.

Checking a Feature Flag/Gate​

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

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

Getting a DynamicConfig​

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

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

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

Logging an Event​

You can get the client with the useStatsigClient hook, and then call logEvent

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

Getting an Experiment​

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

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

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

Getting a Layer​

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

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

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

Loading State​

Dependent on your setup, you may want to wait for the latest values before checking a gate or experiment. If you are using StatsigProviderExpo, you can pass in a loadingComponent prop to display a loading state while the SDK is initializing. If you are using the useClientAsyncInitExpo hook, you can check the isLoading prop to determine if the SDK is still loading.

export function App() {
const loadingComponent = <div>Loading...</div>;

return (
<StatsigProviderExpo
...
loadingComponent={loadingComponent} // <- Pass in the loading component
>
<YourComponent />
</StatsigProviderExpo>
);
}

Advanced​

Expo Without React​

In some scenarios, you may need to use the StatsigClient when you are not in the React component tree. Things like background tasks or handling notifications. For these, you can use the Expo specific StatsigClientExpo.

import { StatsigClientExpo } from '@statsig/expo-bindings';

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

await myClient.initializeAsync();

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

Synchronous Storage with MMKV​

If you are utilizing MMKV in your project, and would prefer to use that instead of the default (AsyncStorage). You can provide you own StorageProvider via StatsigOptions.

Something like:

import { MMKV } from "react-native-mmkv";
import { StorageProvider } from "@statsig/client-core";
import { StatsigProviderExpo } from "@statsig/expo-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 (
<StatsigProviderExpo
sdkKey={YOUR_CLIENT_KEY}
user={{ userID: "a-user" }}
options={{
storageProvider, // <- Passed into StatsigOptions
}}
>
<Text>...</Text>
</StatsigProviderExpo>
);
}

Debugging​

Network Issues​

Some users have reported a ERROR: A networking error occured during POST request messages when first initializing Statsig. This issue is solved in releases of the SDK after 3.1.0, so upgrading your SDK should solve the issue. If it persists, reach out to us in Slack.