npm package: @omniretail/omniflags-react-native
Description: OmniFlags React Native SDK — provider + hooks with built-in AsyncStorage offline cache
Latest version: 1.0.25

# @omniretail/omniflags-react-native

React Native SDK for OmniFlags.

## Installation

```bash
npm install @omniretail/omniflags-react-native @react-native-async-storage/async-storage
```

Follow the [AsyncStorage setup guide](https://react-native-async-storage.github.io/async-storage/docs/install) to link the native module. If you're using Expo:

```bash
npx expo install @react-native-async-storage/async-storage
```

## Quick start

```tsx
import { OmniFlagsProvider, useFlag } from "@omniretail/omniflags-react-native";

function App() {
  return (
    <OmniFlagsProvider sdkKey="your-sdk-key">
      <MyApp />
    </OmniFlagsProvider>
  );
}

function MyApp() {
  const enabled = useFlag("store.new-checkout");
  return enabled ? <NewCheckout /> : <LegacyCheckout />;
}
```

## Provider

```tsx
<OmniFlagsProvider sdkKey="your-sdk-key">
  {children}
</OmniFlagsProvider>
```

| Prop | Type | Description |
|------|------|-------------|
| `sdkKey` | `string` | **Required.** SDK key from the OmniFlags dashboard. |

Flags are persisted to AsyncStorage and refreshed when the app returns to the foreground.

## Hooks

### `useFlag`

```tsx
const enabled = useFlag("store.new-checkout");
const enabled = useFlag("store.new-checkout", { customerId: "cust-123" }); // with context
const enabled = useFlag("store.new-checkout", undefined, false);            // custom default
```

### `useFlagValue`

```tsx
const theme = useFlagValue<string>("store.theme", "light");
const limit = useFlagValue<number>("store.item-limit", 10);
const theme = useFlagValue<string>("store.theme", "light", { businessId: "biz-456" }); // with context
```

### `useFlagVariant`

Returns the full evaluation result — value, variant, reason, and which rule matched.

```tsx
const result = useFlagVariant("store.new-checkout");
// result.value, result.variant, result.reason, result.ruleId, result.errorCode
```

### `useFlagLoading`

Returns the current loading state of the flag client.

```tsx
const { isFetching, isLoading, origin, error } = useFlagLoading();
```

| Field | Type | Description |
|-------|------|-------------|
| `isFetching` | `boolean` | A network request is in flight. |
| `isLoading` | `boolean` | No flags have been loaded yet (first fetch pending). |
| `origin` | `FlagOrigin` | Where the current flags came from: `"NONE"`, `"CACHE"`, or `"SERVER"`. |
| `error` | `Error \| null` | The last fetch error, or `null`. |

```tsx
function FlagGate({ children }: { children: React.ReactNode }) {
  const { isLoading } = useFlagLoading();
  if (isLoading) return <ActivityIndicator />;
  return <>{children}</>;
}
```

### `useOmniFlags`

Low-level access to the underlying client and ready state.

```tsx
const { client, ready } = useOmniFlags();
```

## Context

Context is passed per evaluation call — customer, business, branch, country, etc. There is no persistent context state.

```tsx
function CheckoutButton({ customerId, businessBranchId }: Props) {
  const ctx = { customerId, businessBranchId };
  const enabled = useFlag("store.new-checkout", ctx);
  return enabled ? <NewCheckoutButton /> : <LegacyCheckoutButton />;
}
```

## Flag keys

Keys are namespaced by project: `{projectKey}.{flagKey}`. Find the full flag key in the OmniFlags dashboard on the flag detail page.