---
title: Decide hooks for the React SDK v4+
slug: feature-experimentation/docs/decide-hooks-for-the-react-sdk
docTags: 
createdAt: 2026-08-05T20:39:51.000Z
---

Use the decide methods to return feature flag decisions for a user. Each decision includes whether the flag is enabled and which variation the user receives.

## Decide

Returns a decision for a specific feature flag and user.

**Minimum SDK version** – v4.0.0+

For versions 3.x and earlier, see [React SDK prior to v4](docId\:lG9fwJNrH3MiLZniFQeAs).

## useDecide

Returns a flag decision for a single flag key. This is the primary hook for making feature flag decisions in React components.

### Parameters

| Parameter           | Type   | Description                                                                |
| ------------------- | ------ | -------------------------------------------------------------------------- |
| `flagKey`           | String | The key of the feature flag.                                               |
| `config` (optional) | Object | Configuration object. See [UseDecideConfig](docId\:MQOucnDtzaDdb09UGCF9s). |

### Returns

Returns a `UseDecideResult` object — a discriminated union with three possible states:

| State   | `isLoading` | `error` | `decision`           |
| ------- | ----------- | ------- | -------------------- |
| Loading | `true`      | `null`  | `null`               |
| Error   | `false`     | `Error` | `null`               |
| Success | `false`     | `null`  | `OptimizelyDecision` |

### Example

```javascript
import { useDecide, OptimizelyDecideOption } from '@optimizely/react-sdk';

function MyComponent() {
  const { decision, isLoading, error } = useDecide('product_sort', {
    decideOptions: [OptimizelyDecideOption.INCLUDE_REASONS],
  });

  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;

  const variationKey = decision.variationKey;
  const enabled = decision.enabled;
  const sortMethod = decision.variables['sort_method'];

  return <div>{enabled ? <NewFeature sort={sortMethod} /> : <Default />}</div>;
}
```

### Side effect

Invokes the [decision notification listener](docId\:eyOn7CmG5jWwB3vIm7mt9) if this listener is enabled.

## useDecideAsync

Similar to [useDecide](docId\:MQOucnDtzaDdb09UGCF9s), but uses the underlying async SDK method (`decideAsync`). Use this when your setup involves asynchronous operations such as CMAB (Contextual Multi-Armed Bandit) decisions or async User Profile Service lookups.

### Example

```javascript
import { useDecideAsync } from '@optimizely/react-sdk';

function MyComponent() {
  const { decision, isLoading, error } = useDecideAsync('flag-key');

  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;
  if (decision.enabled) return <NewFeature />;
  return <Default />;
}
```

## useDecideForKeys

Returns decisions for multiple flag keys in a single call.

### Parameters

| Parameter           | Type   | Description                                                                |
| ------------------- | ------ | -------------------------------------------------------------------------- |
| `flagKeys`          | Array  | Array of string flag keys.                                                 |
| `config` (optional) | Object | Configuration object. See [UseDecideConfig](docId\:MQOucnDtzaDdb09UGCF9s). |

### Returns

Returns a `UseDecideMultiResult` object:

| State   | `isLoading` | `error` | `decisions`                                      |
| ------- | ----------- | ------- | ------------------------------------------------ |
| Loading | `true`      | `null`  | `null`                                           |
| Error   | `false`     | `Error` | `null`                                           |
| Success | `false`     | `null`  | Map of flag keys to `OptimizelyDecision` objects |

### Example

```javascript
import { useDecideForKeys } from '@optimizely/react-sdk';

function MyComponent() {
  const { decisions, isLoading, error } = useDecideForKeys(['flag-a', 'flag-b']);

  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;

  const flagA = decisions['flag-a'];
  const flagB = decisions['flag-b'];

  return (
    <div>
      {flagA.enabled && <FeatureA />}
      {flagB.enabled && <FeatureB />}
    </div>
  );
}
```

### Side effects

Invokes the [decision notification listener](docId\:eyOn7CmG5jWwB3vIm7mt9) if this listener is enabled.

## useDecideForKeysAsync

Similar to [useDecideForKeys](docId\:MQOucnDtzaDdb09UGCF9s), but uses the underlying async SDK method. Use this for CMAB decisions or async User Profile Service lookups.

```javascript
import { useDecideForKeysAsync } from '@optimizely/react-sdk';

const { decisions, isLoading, error } = useDecideForKeysAsync(['flag-a', 'flag-b']);
```

## useDecideAll

Returns decisions for all active (unarchived) flags in the project.

### Parameters

| Parameter           | Type   | Description                                                                |
| ------------------- | ------ | -------------------------------------------------------------------------- |
| `config` (optional) | Object | Configuration object. See [UseDecideConfig](docId\:MQOucnDtzaDdb09UGCF9s). |

### Returns

Returns a `UseDecideMultiResult` object (same shape as [useDecideForKeys](docId\:MQOucnDtzaDdb09UGCF9s)).

### Example

```javascript
import { useDecideAll, OptimizelyDecideOption } from '@optimizely/react-sdk';

function MyComponent() {
  const { decisions, isLoading, error } = useDecideAll({
    decideOptions: [OptimizelyDecideOption.ENABLED_FLAGS_ONLY],
  });

  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;

  const flagKeys = Object.keys(decisions);
  return (
    <div>
      {flagKeys.map((key) => (
        <div key={key}>{key}: {decisions[key].variationKey}</div>
      ))}
    </div>
  );
}
```

### Side effects

Invokes the [decision notification listener](docId\:eyOn7CmG5jWwB3vIm7mt9) if this listener is enabled.

## useDecideAllAsync

Similar to [useDecideAll](docId\:MQOucnDtzaDdb09UGCF9s), but uses the underlying async SDK method. Use this for CMAB decisions or async User Profile Service lookups.

```javascript
import { useDecideAllAsync } from '@optimizely/react-sdk';

const { decisions, isLoading, error } = useDecideAllAsync();
```

## UseDecideConfig

The optional configuration object accepted by all decide hooks.

| Property                   | Type  | Description                                                            |
| -------------------------- | ----- | ---------------------------------------------------------------------- |
| `decideOptions` (optional) | Array | Array of [OptimizelyDecideOption](docId\:MQOucnDtzaDdb09UGCF9s) enums. |

## `OptimizelyDecideOption`

The following table lists the `OptimizelyDecideOption` enum with an explanation what happens if you set them. In addition to setting these options individually for a decide hook, you can also set them as global defaults when you instantiate the Optimizely client. See [Initialize the React SDK](docId:9CfwJPUAXUm5OPN0283Fu).

| `OptimizelyDecideOption` enum                        | If set                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OptimizelyDecideOption.DISABLE_DECISION_EVENT`      | Prevents the SDK from dispatching an [impression](../../end-user-docs/measure-and-analyze-results/what-are-impressions-and-decisions-in-feature-experimentation.mdx) event when serving a variation. This disables decision tracking on the [Optimizely Experiment Results page](../../end-user-docs/measure-and-analyze-results/optimizely-experiment-results-page.mdx). The [decision notification listener](../../developer-docs/configure/notification-listeners/decision-notification-listener.mdx) is still called, with `decisionEventDispatched` set to `false`. |
| `OptimizelyDecideOption.ENABLED_FLAGS_ONLY`          | Returns decisions only for flags that are currently enabled. Used with the decide all method and decide for keys method.<br />When this option is not set, the SDK returns all decisions regardless of whether the flag is enabled.                                                                                                                                                                                                                                                                                                                                      |
| `OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE` | Bypasses the user profile service (both lookup and save) for the decision.<br />When this option is not set, user profile service overrides audience targeting, traffic allocation, and experiment mutual exclusion groups.                                                                                                                                                                                                                                                                                                                                              |
| `OptimizelyDecideOption.INCLUDE_REASONS`             | Adds log messages to the reasons field of the decision. Critical errors are always returned, even if this option is not set.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `OptimizelyDecideOption.EXCLUDE_VARIABLES`           | Excludes flag variable values from the decision result. Use this option to minimize the returned decision by skipping large JSON variables.                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `OptimizelyDecideOption.IGNORE_CMAB_CACHE`           | Bypasses the CMAB cache and fetches a fresh decision from the CMAB service. Use when you need real-time decisions that reflect the latest context.                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `OptimizelyDecideOption.INVALIDATE_USER_CMAB_CACHE`  | Removes the cached CMAB decision for this user and experiment before making the decision. Use when user context has changed significantly and you want to ensure a fresh decision.                                                                                                                                                                                                                                                                                                                                                                                       |
| `OptimizelyDecideOption.RESET_CMAB_CACHE`            | Clears all entries from the CMAB cache before making the decision. Use sparingly for testing or cache corruption scenarios.                                                                                                                                                                                                                                                                                                                                                                                                                                              |

The following code sample shows how to set options on the `useDecide` hook and as global defaults when you instantiate the Optimizely client:

```javascript
import {
  createInstance,
  createPollingProjectConfigManager,
  createBatchEventProcessor,
  OptimizelyDecideOption,
  OptimizelyProvider,
  useDecide,
} from '@optimizely/react-sdk';

const optimizely = createInstance({
  projectConfigManager: createPollingProjectConfigManager({
    sdkKey: 'YOUR_SDK_KEY',
  }),
  eventProcessor: createBatchEventProcessor(),
  defaultDecideOptions: [OptimizelyDecideOption.DISABLE_DECISION_EVENT],
});

function FlagComponent() {
  const { decision, isLoading, error } = useDecide('my_flag', {
    decideOptions: [
      OptimizelyDecideOption.ENABLED_FLAGS_ONLY,
      OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE,
    ],
  });

  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;

  return <div>{decision.enabled ? 'Enabled' : 'Disabled'}</div>;
}

function App() {
  return (
    <OptimizelyProvider
      client={optimizely}
      user={{ id: 'user123' }}
    >
      <FlagComponent />
    </OptimizelyProvider>
  );
}
```

## Best practices

- **Early and late invocation**
  - Use the decide all method early in your application's rendering process to load the correct cached content. For example, on the [CDN with an Edge SDK](../../developer-docs/optimizely-feature-experimentation-at-the-edge/content-delivery-networks.mdx).
  - Use the decide method at the point of user interaction or when you must ensure Feature Experimentation records the decision in your experiment analytics.
- **Combining methods** – When using the decide and decide all methods, always pair the decide all method with the decide method for each experiment the user encounters. This prevents discrepancies between served content and analytics data.
- **Parameter management** – Ensure you use the `DISABLE_DECISION_EVENT` option with the decide all method to avoid premature bucketing, then use the decide method to handle the decision event when the user experiences the content.

## Source files

The language and platform source files containing the implementation for the React SDK are available on [GitHub](https://github.com/optimizely/react-sdk).
