Expo Client SDK
Statsig's SDK for Experimentation and Feature Flags in Expo applications.
Set up the SDK
Install the SDK
shellnpx expo install @statsig/expo-bindingsPeer Dependencies
The
@statsig/expo-bindingspackage has peer dependencies which may also need to be installed if they aren't already in your project.shellnpx expo install expo-device expo-application @react-native-async-storage/async-storageInitialize the SDK
Next, initialize the SDK with a client SDK key from the "API Keys" tab on the Statsig console. These keys are safe to embed in a client application.Along with the key, pass in a User Object with the attributes you'd like to target later on in a gate or experiment.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 specificStatsigProviderExpo. This automatically switches out the storage layer used by the SDK, utilizing AsyncStorage instead of LocalStorage (which isn't available in RN environments).tsximport { 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> ); }
Use the SDK
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();
The methods you can call on the client are listed below.
Checking a Feature Flag/Gate
Now that your SDK is initialized, let's check a Feature Gate. 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 (thinkreturn false;) by default.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>
);
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
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 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.
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.
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 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:
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.
import { Button } from 'react-native';
import { useStatsigClient } from '@statsig/expo-bindings';
const { client } = useStatsigClient();
return (
<button
onClick={async () => {
await client.flush();
}}
>
Flush Events
</button>
);
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 StatsigProviderExpo, pass in a loadingComponent prop to display a loading state while the SDK is initializing. If you are using the useClientAsyncInitExpo hook, 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>
);
}
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:
import { useEffect } from 'react';
import { useStatsigClient } from '@statsig/expo-bindings';
const { client } = useStatsigClient();
useEffect(() => {
return () => {
void client.shutdown();
};
}, [client]);
Advanced
Expo Without React
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 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 using MMKV in your project and prefer it over the default (AsyncStorage), provide your ownStorageProvider through StatsigOptions.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 reportedERROR: A networking error occured during POST request messages when first initializing Statsig. Statsig resolved this issue in SDK versions after 3.1.0. Upgrade your SDK to resolve the error. If the error persists, reach out through Slack.Was this helpful?