> For the complete documentation index, see [llms.txt](https://docs.winga.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.winga.me/sdks/react.md).

# @winga/react

`@winga/react` is the React adapter for Winga. You construct a `WingaClient` with [`@winga/js`](/sdks/javascript.md), pass it to a provider, and read flags through hooks that re-render automatically when a flag changes.

***

### Installation

```bash
npm install @winga/js @winga/react
```

`@winga/react` has a peer dependency on **React 19**.

***

### Setup

`WingaProvider` takes a single `client` prop — you construct the `WingaClient` yourself and pass it in. This keeps the provider decoupled from `WingaOptions` and lets React StrictMode work correctly.

#### StrictMode-safe pattern (required)

React StrictMode double-mounts every component in development. If you create the client at module level (a singleton), the first mount's cleanup `dispose()`s it, and the remount calls `on()` on the disposed instance — routing a `CLIENT_DISPOSED` error to `onError` and leaving your hooks frozen at their pre-dispose values. Wrap construction in `useMemo`, keyed on the connection params, so each provider mount gets a fresh client:

```tsx
// app/providers.tsx
import { useMemo } from 'react'
import { Winga } from '@winga/js'
import { WingaProvider } from '@winga/react'

export function Providers({ children }: { children: React.ReactNode }) {
  const client = useMemo(
    () =>
      Winga({
        apiKey: process.env.NEXT_PUBLIC_WINGA_KEY!,
        environment: process.env.NEXT_PUBLIC_ENV ?? 'development',
      }),
    // Re-create the client only when connection params change.
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [process.env.NEXT_PUBLIC_WINGA_KEY, process.env.NEXT_PUBLIC_ENV],
  )

  return <WingaProvider client={client}>{children}</WingaProvider>
}
```

`WingaProvider` calls `client.dispose()` in its `useEffect` cleanup, so the client is always torn down when the provider unmounts.

#### `WingaProviderProps`

| Prop       | Type          | Required | Description                                              |
| ---------- | ------------- | :------: | -------------------------------------------------------- |
| `client`   | `WingaClient` |    Yes   | A client created with `Winga({ ... })` from `@winga/js`. |
| `children` | `ReactNode`   |    Yes   | The subtree that can read flags.                         |

***

### Hooks

All three hooks subscribe via `useSyncExternalStore` and re-render only the components that read a changed flag. Each throws a descriptive error when called outside a `<WingaProvider>`.

#### `useFlag(key)`

Returns the boolean state of a flag.

```tsx
import { useFlag } from '@winga/react'

function CheckoutButton() {
  const isNewCheckout = useFlag('new-checkout')
  return isNewCheckout ? <NewCheckout /> : <LegacyCheckout />
}
```

Outside a provider: `useFlag() must be called inside a <WingaProvider>.`

#### `useFlagValue<T>(key, defaultValue)`

Reads a typed flag value with a required fallback.

```tsx
import { useFlagValue } from '@winga/react'

function Banner() {
  const text = useFlagValue<string>('banner-text', 'Welcome!')
  return <div className="banner">{text}</div>
}
```

For a **non-primitive** `defaultValue` (object or array), stabilise it with `useMemo` so it does not recreate the snapshot on every render:

```tsx
const fallback = useMemo(() => ({ tier: 'free' as const }), [])
const value = useFlagValue('plan', fallback)
```

Outside a provider: `useFlagValue() must be called inside a <WingaProvider>.`

#### `useFlags()`

Returns every flag in the current environment as `Record<string, FlagState>`.

```tsx
import { useFlags } from '@winga/react'

function DebugPanel() {
  const flags = useFlags()
  return <pre>{JSON.stringify(flags, null, 2)}</pre>
}
```

Outside a provider: `useFlags() must be called inside a <WingaProvider>.`

***

### Public exports

`@winga/react` exports exactly:

* `WingaProvider`
* `WingaProviderProps` (type)
* `useFlag`
* `useFlagValue`
* `useFlags`

***

### Next steps

* Full client API and error codes: [`@winga/js`](/sdks/javascript.md).
* Server-side rendering in Next.js: [`@winga/next`](/sdks/nextjs.md) (coming soon).
