Skip to main content

React Client SDK for Statsig

info

These docs are for using our react SDK in a single-user, client side context. For react native mobile clients, try our react native sdk

Background#

The Statsig React SDK builds on top of the React Context and Hooks APIs, which are only supported in React v16.8.0+. If this requirement prevents you from using the SDK, please let us know.

If you are unfamiliar with using React Hooks, be sure to read the rules of hooks.

Also note that this SDK wraps the statsig-js sdk, and reuses a number of concepts introduced in that SDK. This includes:

  • initialization options have the same set of parameters, with additional react-specific parameters.
  • hooks for DynamicConfigs return the same DynamicConfig object
  • the useStatsig hook returns the internal statsig-js sdk, with all the functionality.

Refer to the statsig-js documentation for more information.

Installing the SDK#

You can install the statsig SDK via npm or yarn.

npm install statsig-react

Usage#

How we at Statsig use the SDK, and suggested usage.

At the root of your component tree, wrap your app in a StatsigProvider and set waitForInitialization=true (if you do not wait for initialization, useGate hooks will return false on the first render, and will only update to the actual gate value once SDK initialization completes and Gates are fetched for the passed in user. Similarly, useConfig and useExperiment will return empty dynamic configs).

import { StatsigProvider } from 'statsig-react';
...
<StatsigProvider
sdkKey="<CLIENT_SDK_KEY>"
user={{
userID: <LOGGED_IN_USER_ID>,
email: session?.user?.email ?? undefined,
... // other user parameters
}}
waitForInitialization={true}>
<Component />
</StatsigProvider>

Then, in your app, the useGate, useConfig, and useExperiment hooks will provide the up to date values of Feature Gates, DynamicConfigs, and Experiments (respectively) for the initialized user. If you are unfamiliar with React Hooks, see the rules of hooks.

import { useGate } from 'statsig-react';
...
export default function MyComponent(): JSX.Element {
// only call hooks at the top level of a functional component
const featureOn = useGate(<MY_FEATURE_GATE>).value;
return {featureOn ? <MyComponent /> : null;
}

To logEvents, get the underlying StatsigSDK

import { useStatsig } from 'statsig-react';
...
export default function MyComponent(): JSX.Element {
const statsig = useStatsig();
return
<Button
onClick={() => {
statsig.logEvent('button_clicked);
}}
/>;
}

If you need to check gates/configs in a loop, you can use this same useStatsig hook to avoid using the Feature Gate and Config hooks improperly in a loop.

More Details#

The statsig-react sdk exports the following components:

StatsigProvider#

StatsigProvider is a react context provider which initializes the SDK, and passes down its state to the rest of the react application via a StatsigContext. It takes the following properties:

  • children: React.ReactNode | React.ReactNode[]; - One or more child components
  • sdkKey: string; - A client SDK key from the Statsig Console
  • user: statsig.StatsigUser; - A Statsig User object. Changing this will update the user and Gate values, causing a re-initialization
  • options?: statsig.StatsigOptions; - An optional bag of initialization properties (shared with the statsig-js sdk) for advanced configuration
  • waitForInitialization?: boolean; - Waits for the SDK to initialize with updated values before rendering child components

Hooks#

The SDK exposes Feature Gates, Dynamic Configs, Experiments, and the underlying statsig-js. If you are unfamiliar with hooks, be sure to check out the rules of hooks

useGate#

A react hook to get a Statsig Feature Gate.

Parameters:

  • gateName: string - the name of the gate to check

Returns:

  • GateResult
  • isLoading: boolean; - the loading/initializing state of the SDK
  • value: boolean - the value of the feature gate (false by default)
useConfig#

A react hook to get a Statsig Dynamic Config.

Parameters:

  • configName: string - the name of the config to get

Returns:

  • ConfigResult
  • isLoading: boolean; - the loading/initializing state of the SDK
  • config: DynamicConfig - the backing DynamicConfig (see the statsig-js sdk docs for more information)
useExperiment#

A react hook to get a Statsig Experiment, represented as a DynamicConfig.

Parameters:

  • experimentName: string - the name of the experiment to get

Returns:

  • ConfigResult
  • isLoading: boolean; - the loading/initializing state of the SDK
  • config: DynamicConfig - the backing DynamicConfig (see the statsig-js sdk docs for more information)
useStatsig#

A react hook to get an initialized reference to the statsig-js sdk, or undefined if not initialized. Use this to log events or instead of useGate/useConfig/useExperiment if you are violating the rules of hooks. For example, to check gates in a loop, useStatsig to get a reference to the sdk, and call checkGate in the loop.

Parameters: none

Returns:

  • statsig | undefined - a reference to the initialized statsig-js sdk, or undefined if not initialized
StatsigContext#

StatsigContext is a react context used internally by the SDK to manage internal state. You should not need to use the StatsigContext directly, as the Provider and Hooks interface with it for you. It tracks the following state:

  • initialized: boolean; the initialization state of the SDK
  • statsigPromise: React.MutableRefObject<Promise<void>> | null; a reference to a promise which resolves once SDK initialization is complete
  • statsig: typeof statsig | undefined; the statsig-js SDK, or undefined if uninitialized

Testing#

Internally at Statsig, we use this jest mock to test our components:

jest.mock('statsig-react', () => {
return {
StatsigProvider: ({ children }: { children: React.ReactNode }) => children,
useGate: () => {
return false;
},
useConfig: () => {
return {};
},
useExperiment: () => {},
useStatsig: () => {
return {
logEvent: () => {},
checkGate: () => false,
getConfig: () => {
return {
get: (name: string, fallback: any) => fallback,
getValue: (name: string, fallback: any) => fallback,
};
},
};
},
};
});