npm package: @splitlab/react
Description: React bindings for SplitLab A/B testing and feature flags
Latest version: 0.13.0

# @splitlab/react

React hooks and providers for SplitLab A/B testing and feature flags. Wraps [`@splitlab/js-client`](https://www.npmjs.com/package/@splitlab/js-client) with a React-friendly API.

## Installation

```bash
npm install @splitlab/react
```

## Quick Start

```tsx
import { SplitLabProvider, useVariant, useFeatureFlag } from '@splitlab/react';

function App() {
  return (
    <SplitLabProvider config={{
      apiKey: 'ot_live_abc123',
      baseUrl: 'https://splitlab.cc',
    }}>
      <CheckoutPage />
    </SplitLabProvider>
  );
}

function CheckoutPage() {
  const variant = useVariant('checkout-btn');   // 'control' | 'variant_a' | null
  const darkMode = useFeatureFlag('dark-mode'); // true | false

  return (
    <div className={darkMode ? 'dark' : ''}>
      {variant === 'variant_a' ? <GreenButton /> : <BlueButton />}
    </div>
  );
}
```

## Providers

### `<SplitLabProvider>`

Initializes the SDK client and provides it to the component tree. The client fetches config on mount and evaluates experiments/flags locally (< 1ms).

```tsx
<SplitLabProvider config={{
  apiKey: 'ot_live_abc123',
  baseUrl: 'https://splitlab.cc',
  // All @splitlab/js-client options are supported:
  trackPageviews: true,
  realtimeUpdates: true,
  onConfigUpdate: () => console.log('Config updated'),
}}>
  {children}
</SplitLabProvider>
```

### `<SplitLabBootstrapProvider>`

For SSR apps. Hydrates the client synchronously from server-generated bootstrap data — no config fetch, no loading flash.

```tsx
import { SplitLabBootstrapProvider } from '@splitlab/react';
import type { BootstrapData } from '@splitlab/react';

// Bootstrap data generated server-side via @splitlab/node's ctx.getBootstrapData()
const bootstrap: BootstrapData = JSON.parse(window.__SPLITLAB_BOOTSTRAP__);

<SplitLabBootstrapProvider
  config={{ apiKey: 'ot_live_abc123', baseUrl: 'https://splitlab.cc' }}
  bootstrap={bootstrap}
>
  {children}
</SplitLabBootstrapProvider>
```

## Hooks

### `useVariant(experimentKey): string | null`

Returns the assigned variant key, or `null` if the user is excluded or the SDK is still loading. Fires a `$exposure` event on first access (once per experiment per client lifetime).

```tsx
const variant = useVariant('pricing-page');
if (variant === 'annual_first') showAnnualFirst();
```

### `useFeatureFlag(flagKey): boolean`

Returns `true` if the flag is enabled, `false` otherwise (including while loading).

```tsx
if (useFeatureFlag('new-onboarding')) return <NewOnboarding />;
return <ClassicOnboarding />;
```

### `useSplitLab(): SplitLabClient`

Returns the underlying client instance for advanced operations (tracking, identity, etc.). Throws if called outside a provider.

```tsx
const client = useSplitLab();

const handlePurchase = async () => {
  await client.track('purchase', { value: 49.99 });
};

const handleLogin = async (userId: string) => {
  await client.identify(userId);
};
```

## Loading States

Hooks return safe defaults while the SDK initializes:
- `useVariant()` returns `null` (control / no treatment)
- `useFeatureFlag()` returns `false` (off)

Use `<SplitLabBootstrapProvider>` to eliminate loading states entirely in SSR apps.

## Building

```bash
npm run build   # ESM + CJS + types → dist/
npm run dev     # Watch mode
```