On this page

React Client SDK

Use Statsig in React apps with hooks, providers, and optional plugins for session replay and auto capture.

Set Up the SDK

  1. Install the SDK

    If you need a starter project, follow the official React quickstart. Looking for Next.js instead? Go to the Next.js SDK docs.

    AI-powered Setup

    Setup Statsig in 90 seconds by copying this AI prompt into your IDE:

    text
    You are a frontend engineer integrating the Statsig SDK into a React app. Follow these instructions carefully:
    1. Install the required Statsig packages:
         npm install @statsig/react-bindings @statsig/session-replay @statsig/web-analytics
    
    2. In the main component file (`App.jsx` or `App.tsx`):
       - Import `StatsigProvider` and `useClientAsyncInit` from `@statsig/react-bindings`
       - Import `StatsigAutoCapturePlugin` from `@statsig/web-analytics` and `StatsigSessionReplayPlugin` from `@statsig/session-replay`
       - Initialize the SDK using your client key: 'YOUR-CLIENT-API-KEY'
       - Use `userID` from an existing variable if it's already declared in the file; otherwise, default to `'a-user'`
       - Wrap the existing app content inside `<StatsigProvider>`, using `<div>Loading...</div>` as the `loadingComponent`
    
    3. DO NOT remove any existing JSX content from the component. Just wrap it.
    
    4. Here is what the final file structure should look like:
    
        import { StatsigProvider, useClientAsyncInit } from '@statsig/react-bindings';
        import { StatsigAutoCapturePlugin } from '@statsig/web-analytics';
        import { StatsigSessionReplayPlugin } from '@statsig/session-replay';
        import YourApp from './YourApp';
    
        function App() {
          const id = typeof userID !== 'undefined' ? userID : 'a-user';
          const { client } = useClientAsyncInit(
            'YOUR-CLIENT-API-KEY',
            { userID: id },
            { plugins: [new StatsigAutoCapturePlugin(), new StatsigSessionReplayPlugin()] }
          );
    
          return (
            <StatsigProvider client={client} loadingComponent={<div>Loading...</div>}>
              <YourApp />
            </StatsigProvider>
          );
        }
    
    5. Ask the user to provide their CLIENT-API-KEY and insert it where prompted above.
    

    Install Packages

    bash
    npm install @statsig/react-bindings
    

    Add @statsig/session-replay and @statsig/web-analytics if you plan to enable Session Replay or Auto Capture.

  2. Initialize 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.

    Wrap Your App With StatsigProvider

    Provide your client SDK key and initial user when you render the provider.

    tsx
    import { StatsigProvider } from '@statsig/react-bindings';
    
    function App() {
      return (
        <StatsigProvider sdkKey="client-KEY" user={{ userID: '1234', email: 'example@statsig.com' }}>
          <div>Hello world</div>
        </StatsigProvider>
      );
    }
    

    Typical Project Structure

    Most projects render a root component inside the provider.

    tsx
    // App.tsx
    import RootPage from './RootPage';
    import { StatsigProvider } from '@statsig/react-bindings';
    
    export default function App() {
      return (
        <StatsigProvider sdkKey="client-KEY" user={{ userID: '1234' }}>
          <RootPage />
        </StatsigProvider>
      );
    }
    
    tsx
    // RootPage.tsx
    export default function RootPage() {
      return <div>Hello World</div>;
    }
    
    Need to balance startup speed with freshness? Review Initialization Strategies for bootstrap and async options.

Use the SDK

Use useStatsigClient inside components to retrieve the client when you need to evaluate something.

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

const { client } = useStatsigClient();

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 (think return false;) by default.
tsx
import {
  useFeatureGate,
  useGateValue,
  useStatsigClient,
} from '@statsig/react-bindings';

const { checkGate } = useStatsigClient();
const gateValue = useGateValue('my_gate');
const gate = useFeatureGate('my_gate');

return (
  <div>
    {checkGate('my_gate') && <p>Passing</p>}
    {gateValue && <p>Passing</p>}
    {gate.value && <p>Passing ({gate.details.reason})</p>}
  </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:

tsx
import { useDynamicConfig, useStatsigClient } from '@statsig/react-bindings';

const config = useDynamicConfig('my_dynamic_config');
const { getDynamicConfig } = useStatsigClient();

return (
  <div>
    <p>Reason: {config.details.reason}</p>
    <p>Value: {config.get('a_value', 'fallback_value')}</p>
    <p>Another Value: {getDynamicConfig('my_dynamic_config').get('a_bool', false)}</p>
  </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.
tsx
import { useExperiment, useStatsigClient } from '@statsig/react-bindings';

const experiment = useExperiment('my_experiment');
const { getExperiment } = useStatsigClient();

return (
  <div>
    <p>Group: {getExperiment('my_experiment').groupName}</p>
    <p>Value: {experiment.get('a_value', 'fallback_value')}</p>
  </div>
);
tsx
import { useLayer, useStatsigClient } from '@statsig/react-bindings';

const layer = useLayer('my_layer');
const { getLayer } = useStatsigClient();

return (
  <div>
    <p>Group: {getLayer('my_layer').groupName}</p>
    <p>Value: {layer.get('a_value', 'fallback_value')}</p>
  </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:

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

const { logEvent } = useStatsigClient();

return <button onClick={() => logEvent('my_event')}>Click Me</button>;

Flushing Logged Events

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

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

const { client } = useStatsigClient();

return (
  <button
    onClick={async () => {
      await client.flush();
    }}
  >
    Flush Events
  </button>
);

Parameter Stores

Parameter Stores hold a set of parameters for your app. These parameters can be remapped dynamically from a static value to a Statsig entity (Feature Gates, Experiments, and Layers), so you can decouple your code from the configuration in Statsig. Refer to Parameter Stores for details.

Manage Users

Updating User Properties

Call updateUserAsync when a user logs in or when you collect richer attributes.

tsx
import { useGateValue, useStatsigUser } from '@statsig/react-bindings';

export default function AccountBanner() {
  const gateValue = useGateValue('check_user');
  const { updateUserAsync } = useStatsigUser();

  return (
    <div>
      <div>Gate is {gateValue ? 'passing' : 'failing'}.</div>
      <button onClick={() => updateUserAsync({ userID: '2' })}>Login</button>
    </div>
  );
}

Loading State

To wait for the latest values during initialization, use either the provider or the async hook.

tsx
import { StatsigProvider } from '@statsig/react-bindings';

export function App() {
  return (
    <StatsigProvider
      sdkKey="client-KEY"
      user={{ userID: 'a-user' }}
      loadingComponent={<div>Loading...</div>}
    >
      <YourComponent />
    </StatsigProvider>
  );
}

React Hooks

Hooks that read gates, configs, experiments, or layers will log exposures on render. Use useStatsigClient to defer checks until you actually change the UI.

Feature Gate Hooks

  • Recommended: useStatsigClient().checkGate logs when invoked.
  • useGateValue returns the boolean value and logs immediately.
  • useFeatureGate returns the full gate object with details.
tsx
import {
  useFeatureGate,
  useGateValue,
  useStatsigClient,
} from '@statsig/react-bindings';

const { checkGate } = useStatsigClient();
const gateValue = useGateValue('my_gate');
const gate = useFeatureGate('my_gate');

return (
  <div>
    {checkGate('my_gate') && <p>Passing</p>}
    {gateValue && <p>Passing</p>}
    {gate.value && <p>Passing ({gate.details.reason})</p>}
  </div>
);

Dynamic Config Hooks

  • Recommended: useStatsigClient().getDynamicConfig defers exposure until called.
  • useDynamicConfig logs on render.
tsx
import { useDynamicConfig, useStatsigClient } from '@statsig/react-bindings';

const config = useDynamicConfig('my_dynamic_config');
const { getDynamicConfig } = useStatsigClient();

return (
  <div>
    <p>Reason: {config.details.reason}</p>
    <p>Value: {config.get('a_value', 'fallback_value')}</p>
    <p>Another Value: {getDynamicConfig('my_dynamic_config').get('a_bool', false)}</p>
  </div>
);

Experiment Hooks

  • Recommended: useStatsigClient().getExperiment to control exposures.
  • useExperiment logs on render.
tsx
import { useExperiment, useStatsigClient } from '@statsig/react-bindings';

const experiment = useExperiment('my_experiment');
const { getExperiment } = useStatsigClient();

return (
  <div>
    <p>Group: {getExperiment('my_experiment').groupName}</p>
    <p>Value: {experiment.get('a_value', 'fallback_value')}</p>
  </div>
);

Layer Hooks

Layers only log exposures when you call .get().

tsx
import { useLayer, useStatsigClient } from '@statsig/react-bindings';

const layer = useLayer('my_layer');
const { getLayer } = useStatsigClient();

return (
  <div>
    <p>Group: {getLayer('my_layer').groupName}</p>
    <p>Value: {layer.get('a_value', 'fallback_value')}</p>
  </div>
);

Parameter Store Hooks

tsx
import { useParameterStore } from '@statsig/react-bindings';

function MyComponent() {
  const store = useParameterStore('my_parameter_store');
  const title = store.get('page_title', 'Default Title');
  const maxItems = store.get('max_items', 10);
  const isEnabled = store.get('feature_enabled', false);

  const storeNoExposure = useParameterStore('my_parameter_store', {
    disableExposureLog: true,
  });

  return <div>{title}</div>;
}

Log Events From Hooks

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

const { logEvent } = useStatsigClient();

return <button onClick={() => logEvent('my_event')}>Click Me</button>;

StatsigUser Hook

tsx
import { useStatsigUser } from '@statsig/react-bindings';

const { user, updateUserSync } = useStatsigUser();

return (
  <div>
    <p>Current User: {user.userID}</p>
    <button onClick={() => updateUserSync({ userID: 'some-other-user' })}>
      Update User
    </button>
  </div>
);

Direct Access to the Client

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

const { client } = useStatsigClient();
console.log('stableID', client.getContext().stableID);

Client Initialization Hooks

  • useClientAsyncInit: fetches the latest values before rendering.
  • useClientBootstrapInit: bootstrap from server-provided values.
You can also initialize your own client instance manually. Refer to Initialization Strategies for alternatives.

Statsig Options

loggingEnabledLoggingEnabledOptiondefault: "browser-only"

Controls logging behavior.

  • browser-only (default): log events from browser environments.
  • disabled: never send events.
  • always: log in every environment, including non-browser contexts.

Use loggingEnabled: 'disabled' instead.

disableStableIDbooleandefault: "false"

Skip generating a device-level Stable ID.

disableEvaluationMemoizationbooleandefault: "false"

Recompute every evaluation instead of using the memoized result.

initialSessionIDstring

Override the generated session ID.

enableCookiesbooleandefault: "false"

Persist Stable ID in cookies for cross-domain tracking.

disableStorageboolean

Prevent any local storage writes (disables caching).

networkConfigNetworkConfig

Override network endpoints per request type.

environmentStatsigEnvironment

Set environment-wide defaults (for example { tier: 'staging' }).

logLevelLogLeveldefault: "Warn"

Console verbosity.

loggingBufferMaxSizenumberdefault: "50"

Max events per log batch.

loggingIntervalMsnumberdefault: "10_000"

Interval between automatic flushes.

overrideAdapterOverrideAdapter

Modify evaluations before returning them.

includeCurrentPageUrlWithEventsbooleandefault: "true"

Attach the current page URL to logged events.

disableStatsigEncodingbooleandefault: "false"

Send requests without Statsig-specific encoding.

logEventCompressionModeLogEventCompressionModedefault: "Enabled"

Control compression for batched events.

Use logEventCompressionMode instead.

dataAdapterEvaluationsDataAdapter

Provide a custom data adapter to control caching/fetching.

customUserCacheKeyFuncCustomCacheKeyGenerator

Override cache key generation for stored evaluations.

Testing

Mock Statsig hooks in Jest to isolate component logic.

tsx
import { StatsigProvider, useFeatureGate, useExperiment } from '@statsig/react-bindings';

function Content() {
  const gate = useFeatureGate('a_gate');
  const experiment = useExperiment('an_experiment');

  return (
    <div>
      <div data-testid="gate_test">a_gate: {gate.value ? 'Pass' : 'Fail'}</div>
      <div data-testid="exp_test">
        an_experiment: {experiment.get('my_param', 'fallback')}
      </div>
    </div>
  );
}

function App() {
  return (
    <StatsigProvider
      sdkKey={YOUR_CLIENT_KEY}
      user={{ userID: 'a-user' }}
      options={{
        networkConfig: {
          // Optional – disable network requests in tests
          preventAllNetworkTraffic:
            typeof process !== 'undefined' && process.env['NODE_ENV'] === 'test',
        },
      }}
    >
      <Content />
    </StatsigProvider>
  );
}
tsx
import { render, screen } from '@testing-library/react';
import * as ReactBindings from '@statsig/react-bindings';

jest.mock('@statsig/react-bindings', () => ({
  ...jest.requireActual('@statsig/react-bindings'),
  useFeatureGate: () => ({ value: true }),
  useExperiment: () => ({ get: () => 'my_value' }),
}));

test('renders gate pass', async () => {
  render(<App />);
  const elem = await screen.findByTestId('gate_test');
  expect(elem.textContent).toContain('Pass');
});

test('renders experiment value', async () => {
  render(<App />);
  const elem = await screen.findByTestId('exp_test');
  expect(elem.textContent).toContain('my_value');
});

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-bindings';

const { client } = useStatsigClient();

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

Session Replay

Install @statsig/session-replay and register the plugin to record user sessions.

tsx
import { StatsigProvider, useClientAsyncInit } from '@statsig/react-bindings';
import { StatsigSessionReplayPlugin } from '@statsig/session-replay';

function App() {
  const { client } = useClientAsyncInit(
   'client-KEY',
    { userID: 'a-user' },
    { plugins: [new StatsigSessionReplayPlugin()] },
  );

  return (
    <StatsigProvider client={client} loadingComponent={<div>Loading...</div>}>
      <div>Hello World</div>
    </StatsigProvider>
  );
}

Web Analytics / Auto Capture

By including the @statsig/web-analytics package in your project, you can automatically capture common web events like clicks and page views.For more information on filtering events, enabling console log capture, and other configuration options available in web analytics, refer to the Web Analytics Configuration documentation.
tsx
import { StatsigProvider, useClientAsyncInit } from '@statsig/react-bindings';
import { StatsigAutoCapturePlugin } from '@statsig/web-analytics';

function App() {
  const { client } = useClientAsyncInit(
   'client-KEY',
    { userID: 'a-user' },
    { plugins: [new StatsigAutoCapturePlugin()] },
  );

  return (
    <StatsigProvider client={client} loadingComponent={<div>Loading...</div>}>
      <div>Hello World</div>
    </StatsigProvider>
  );
}

Using Persistent Evaluations

To keep experiment variants stable across rerenders or user transitions, use persistent storage. The React integration mirrors the JavaScript workflow and you can adapt the Next.js sample to your setup.Read more in Client Persistent Assignment.

Additional Resources

Was this helpful?