npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@optimizely/react-sdk

v3.4.0

Published

React SDK for Optimizely Feature Experimentation, Optimizely Full Stack (legacy), and Optimizely Rollouts

Readme

Optimizely React SDK

This repository houses the React SDK for use with Optimizely Feature Experimentation and Optimizely Full Stack (legacy).

Optimizely Feature Experimentation is an A/B testing and feature management tool for product development teams that enables you to experiment at every step. Using Optimizely Feature Experimentation allows for every feature on your roadmap to be an opportunity to discover hidden insights. Learn more at Optimizely.com, or see the developer documentation.

Optimizely Rollouts is free feature flags for development teams. You can easily roll out and roll back features in any application without code deploys, mitigating risk for every feature on your roadmap.

Get Started

Refer to the React SDK's developer documentation for detailed instructions on getting started with using the SDK.

For React Native, review the React Native developer documentation.

Features

  • Automatic datafile downloading
  • User ID + attributes memoization
  • Render blocking until datafile is ready via a React API
  • Optimizely timeout (only block rendering up to the number of milliseconds you specify)
  • Library of React components and hooks to use with feature flags

Compatibility

The React SDK is compatible with React 16.8.0 +

Example

import { createInstance, OptimizelyProvider, useDecision } from '@optimizely/react-sdk';

const optimizelyClient = createInstance({
  sdkKey: 'your-optimizely-sdk-key',
});

function MyComponent() {
  const [decision] = useDecision('sort-algorithm');
  return (
    <React.Fragment>
      <SearchComponent algorithm={decision.variables.algorithm} />
      {decision.variationKey === 'relevant_first' && <RelevantFirstList />}
      {decision.variationKey === 'recent_first' && <RecentFirstList />}
    </React.Fragment>
  );
}

class App extends React.Component {
  render() {
    return (
      <OptimizelyProvider
        optimizely={optimizelyClient}
        timeout={500}
        user={{ id: window.userId, attributes: { plan_type: 'bronze' } }}
      >
        <MyComponent />
      </OptimizelyProvider>
    );
  }
}

Install the SDK

npm install @optimizely/react-sdk

For React Native, installation instruction is bit different. Check out the

Use the React SDK

Initialization

createInstance

The ReactSDKClient client created via createInstance is the programmatic API to evaluating features and experiments and tracking events. The ReactSDKClient is what powers the rest of the ReactSDK internally.

arguments

  • config : object Object with SDK configuration parameters. This has the same format as the object passed to the createInstance method of the core @optimizely/javascript-sdk module. For details on this object, see the following pages from the developer docs:

returns

  • A ReactSDKClient instance.
import { OptimizelyProvider, createInstance } from '@optimizely/react-sdk';

const optimizely = createInstance({
  datafile: window.optimizelyDatafile,
});

<OptimizelyProvider>

Required at the root level. Leverages React’s Context API to allow access to the ReactSDKClient to the useDecision hook.

props

| Prop | Type | Required | Description | | --- | --- | --- | --- | | optimizely | ReactSDKClient | Yes | Instance created from createInstance | | user | { id: string; attributes?: { [key: string]: any } } | Promise | No | User info object — id and attributes will be passed to the SDK for every feature flag, A/B test, or track call. Can also be a Promise for the same kind of object. | | timeout | number | No | The amount of time for useDecision to return null flag Decision while waiting for the SDK instance to become ready, before resolving. | | isServerSide | boolean | No | Must pass true for server side rendering. | | userId | string | No | Deprecated, prefer user instead. Another way to provide user id. The user prop takes precedence when both are provided. | | userAttributes | object | No | Deprecated, prefer user instead. Another way to provide user attributes. The user prop takes precedence when both are provided. | | qualifiedSegments | string[] \| null | No | Pre-fetched ODP audience segments for the user. Useful during SSR where async segment fetching is unavailable. Use getQualifiedSegments to obtain these segments server-side. |

Readiness

Before rendering real content, both the datafile and the user must be available to the SDK.

Load the datafile synchronously

Synchronous loading is the preferred method to ensure that Optimizely is always ready and doesn't add any delay or asynchronous complexity to your application. When initializing with both the SDK key and datafile, the SDK will use the given datafile to start, then download the latest version of the datafile in the background.

import { OptimizelyProvider, createInstance } from '@optimizely/react-sdk';

const optimizelyClient = createInstance({
  datafile: window.optimizelyDatafile,
  sdkKey: 'your-optimizely-sdk-key', // Optimizely environment key
});

class AppWrapper extends React.Component {
  render() {
    return (
      <OptimizelyProvider optimizely={optimizelyClient} user={{ id: window.userId }}>
        <App />
      </OptimizelyProvider>
    );
  }
}

Load the datafile asynchronously

If you don't have the datafile downloaded, the ReactSDKClient can fetch the datafile for you. However, instead of waiting for the datafile to fetch before you render your app, you can immediately render your app and provide a timeout option to <OptimizelyProvider optimizely={optimizely} timeout={200}>. The useDecision hook returns isClientReady and didTimeout. You can use these to block rendering of component until the datafile loads or the timeout is over.

import { OptimizelyProvider, createInstance, useDecision } from '@optimizely/react-sdk';

const optimizelyClient = createInstance({
  sdkKey: 'your-optimizely-sdk-key', // Optimizely environment key
});

function MyComponent() {
  const [decision, isClientReady, didTimeout] = useDecision('the-flag');
  return (
    <React.Fragment>
      {isClientReady && <div>The Component</div>}
      {didTimeout && <div>Default Component</div>}
      {/* If client is not ready and time out has not occured yet, do not render anything */}
    </React.Fragment>
  );
}

class App extends React.Component {
  render() {
    return (
      <OptimizelyProvider
        optimizely={optimizelyClient}
        timeout={500}
        user={{ id: window.userId, attributes: { plan_type: 'bronze' } }}
      >
        <MyComponent />
      </OptimizelyProvider>
    );
  }
}

Set user asynchronously

If user information is synchronously available, it can be provided as the user object prop, as in prior examples. But, if user information must be fetched asynchronously, the user prop can be a Promise for a user object with the same properties (id and attributes):

import { OptimizelyProvider, createInstance } from '@optimizely/react-sdk';
import { fetchUser } from './user';

const optimizely = createInstance({
  datafile: window.optimizelyDatafile,
});

const userPromise = fetchUser(); // fetchUser returns a Promise for an object with { id, attributes }

class AppWrapper extends React.Component {
  render() {
    return (
      <OptimizelyProvider optimizely={optimizely} user={userPromise}>
        <App />
      </OptimizelyProvider>
    );
  }
}

useDecision Hook

A React Hook to retrieve the decision result for a flag key, optionally auto updating that decision based on underlying user or datafile changes.

arguments

  • flagKey : string The key of the feature flag.
  • options : Object
    • autoUpdate : boolean (optional) If true, this hook will update the flag decision in response to datafile or user changes. Default: false.
    • timeout : number (optional) Client timeout as described in the OptimizelyProvider section. Overrides any timeout set on the ancestor OptimizelyProvider.
    • decideOption: OptimizelyDecideOption[] (optional) Array of OptimizelyDecideOption enums.
  • overrides : Object
    • overrideUserId : string (optional) Override the userId to be used to obtain the decision result for this hook.
    • overrideAttributes : optimizely.UserAttributes (optional) Override the user attributes to be used to obtain the decision result for this hook.

returns

  • Array of:

    • decision : OptimizelyDecision - Decision result for the flag key.
    • clientReady : boolean - Whether or not the underlying ReactSDKClient instance is ready or not.
    • didTimeout : boolean - Whether or not the underlying ReactSDKClient became ready within the allowed timeout range.

    Note: clientReady can be true even if didTimeout is also true. This indicates that the client became ready after the timeout period.

Render something if flag is enabled

import { useEffect } from 'react';
import { useDecision } from '@optimizely/react-sdk';

function LoginComponent() {
  const [decision, clientReady] = useDecision(
    'login-flag',
    { autoUpdate: true },
    {
      /* (Optional) User overrides */
    }
  );
  useEffect(() => {
    document.title = decision.enabled ? 'login-new' : 'login-default';
  }, [decision.enabled]);

  return (
    <p>
      <a href={decision.enabled ? '/login-new' : '/login-default'}>Click to login</a>
    </p>
  );
}

withOptimizely

Any component under the <OptimizelyProvider> can access the Optimizely ReactSDKClient via the higher-order component (HoC) withOptimizely.

arguments

  • Component : React.Component Component which will be enhanced with the following props:
    • optimizely : ReactSDKClient The client object which was passed to the OptimizelyProvider
    • optimizelyReadyTimeout : number | undefined The timeout which was passed to the OptimizelyProvider
    • isServerSide : boolean Value that was passed to the OptimizelyProvider

returns

  • A wrapped component with additional props as described above

Example

import { withOptimizely } from '@optimizely/react-sdk';

class MyComp extends React.Component {
  constructor(props) {
    super(props);
    const { optimizely } = this.props;
    const decision = optimizely.decide('feat1');

    this.state = {
      decision.enabled,
      decision.variables,
    };
  }

  render() {}
}

const WrappedMyComponent = withOptimizely(MyComp);

Note: The optimizely client object provided via withOptimizely is automatically associated with the user prop passed to the ancestor OptimizelyProvider - the id and attributes from that user object will be automatically forwarded to all appropriate SDK method calls. So, there is no need to pass the userId or attributes arguments when calling methods of the optimizely client object, unless you wish to use different userId or attributes than those given to OptimizelyProvider.

useContext

Any component under the <OptimizelyProvider> can access the Optimizely ReactSDKClient via the OptimizelyContext with useContext.

arguments

  • OptimizelyContext : React.Context<OptimizelyContextInterface> The Optimizely context initialized in a parent component (or App).

returns

  • Wrapped object:
    • optimizely : ReactSDKClient The client object which was passed to the OptimizelyProvider
    • isServerSide : boolean Value that was passed to the OptimizelyProvider
    • timeout : number | undefined The timeout which was passed to the OptimizelyProvider

Example

import React, { useContext } from 'react';
import { OptimizelyContext } from '@optimizely/react-sdk';

function MyComponent() {
  const { optimizely, isServerSide, timeout } = useContext(OptimizelyContext);
  const decision = optimizely.decide('my-feature');
  const onClick = () => {
    optimizely.track('signup-clicked');
    // rest of your click handling code
  };
  return (
    <>
      {decision.enabled && <p>My feature is enabled</p>}
      {!decision.enabled && <p>My feature is disabled</p>}
      {decision.variationKey === 'control-variation' && <p>Current Variation</p>}
      {decision.variationKey === 'experimental-variation' && <p>Better Variation</p>}
      <button onClick={onClick}>Sign Up!</button>
    </>
  );
}

Tracking

Use the built-in useTrackEvent hook to access the track method of optimizely instance

import { useTrackEvent } from '@optimizely/react-sdk';

function SignupButton() {
  const [track, clientReady, didTimeout] = useTrackEvent();

  const handleClick = () => {
    if (clientReady) {
      track('signup-clicked');
    }
  };

  return <button onClick={handleClick}>Signup</button>;
}

Or you can use the withOptimizely HoC.

import { withOptimizely } from '@optimizely/react-sdk';

class SignupButton extends React.Component {
  onClick = () => {
    const { optimizely } = this.props;
    optimizely.track('signup-clicked');
    // rest of click handler
  };

  render() {
    <button onClick={this.onClick}>Signup</button>;
  }
}

const WrappedSignupButton = withOptimizely(SignupButton);

Note: As mentioned above, the optimizely client object provided via withOptimizely is automatically associated with the user prop passed to the ancestor OptimizelyProvider. There is no need to pass userId or attributes arguments when calling track, unless you wish to use different userId or attributes than those given to OptimizelyProvider.

ReactSDKClient

The following type definitions are used in the ReactSDKClient interface:

  • UserAttributes : { [name: string]: any }
  • User : { id: string | null, attributes: userAttributes }
  • VariableValuesObject : { [key: string]: any }
  • EventTags : { [key: string]: string | number | boolean; }

ReactSDKClient instances have the methods/properties listed below. Note that in general, the API largely matches that of the core @optimizely/optimizely-sdk client instance, which is documented on the Optimizely Feature Experimentation developer docs site. The major exception is that, for most methods, user id & attributes are optional arguments. ReactSDKClient has a current user. This user's id & attributes are automatically applied to all method calls, and overrides can be provided as arguments to these method calls if desired.

| Method / Property | Signature | Description | | --- | --- | --- | | onReady | (opts?: { timeout?: number }): Promise<onReadyResult> | Returns a Promise that fulfills with an onReadyResult object representing the initialization process. The instance is ready when it has fetched a datafile and a user is available (via setUser being called with an object, or a Promise passed to setUser becoming fulfilled). If the timeout period happens before the client instance is ready, the onReadyResult object will contain an additional key, dataReadyPromise, which can be used to determine when, if ever, the instance does become ready. | | user | User | The current user associated with this client instance. | | setUser | (userInfo: User \| Promise<User>, qualifiedSegments?: string[]): Promise<void> | Call this to update the current user. Optionally pass qualifiedSegments to set pre-fetched ODP audience segments on the user context. | | onUserUpdate | (handler: (userInfo: User) => void): () => void | Subscribe a callback to be called when this instance's current user changes. Returns a function that will unsubscribe the callback. | | decide | (key: string, options?: OptimizelyDecideOption[], overrideUserId?: string, overrideAttributes?: UserAttributes): OptimizelyDecision | Returns a decision result for a flag key for a user. The decision result is returned in an OptimizelyDecision object, and contains all data required to deliver the flag rule. | | decideAll | (options?: OptimizelyDecideOption[], overrideUserId?: string, overrideAttributes?: UserAttributes): { [key: string]: OptimizelyDecision } | Returns decisions for all active (unarchived) flags for a user. | | decideForKeys | (keys: string[], options?: OptimizelyDecideOption[], overrideUserId?: string, overrideAttributes?: UserAttributes): { [key: string]: OptimizelyDecision } | Returns an object of decision results mapped by flag keys. | | activate | (experimentKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): string \| null | Activate an experiment, and return the variation for the given user. | | getVariation | (experimentKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): string \| null | Return the variation for the given experiment and user. | | getFeatureVariables | (featureKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): VariableValuesObject | Deprecated since 2.1.0. Decide and return variable values for the given feature and user. Use getAllFeatureVariables instead. | | getFeatureVariableString | (featureKey: string, variableKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): string \| null | Decide and return the variable value for the given feature, variable, and user. | | getFeatureVariableInteger | (featureKey: string, variableKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): number \| null | Decide and return the variable value for the given feature, variable, and user. | | getFeatureVariableBoolean | (featureKey: string, variableKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): boolean \| null | Decide and return the variable value for the given feature, variable, and user. | | getFeatureVariableDouble | (featureKey: string, variableKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): number \| null | Decide and return the variable value for the given feature, variable, and user. | | isFeatureEnabled | (featureKey: string, overrideUserId?: string, overrideAttributes?: UserAttributes): boolean | Return the enabled status for the given feature and user. | | getEnabledFeatures | (overrideUserId?: string, overrideAttributes?: UserAttributes): Array<string> | Return the keys of all features enabled for the given user. | | track | (eventKey: string, overrideUserId?: string \| EventTags, overrideAttributes?: UserAttributes, eventTags?: EventTags): void | Track an event to the Optimizely results backend. | | setForcedVariation | (experiment: string, overrideUserIdOrVariationKey: string, variationKey?: string \| null): boolean | Set a forced variation for the given experiment, variation, and user. Note: triggers a re-render of all useExperiment hooks and OptimizelyExperiment components using that client. | | getForcedVariation | (experiment: string, overrideUserId?: string): string \| null | Get the forced variation for the given experiment, variation, and user. |

Rollout or experiment a feature user-by-user

To rollout or experiment on a feature by user rather than by random percentage, you will use Attributes and Audiences. To do this, follow the documentation on how to run a beta using the React code samples.

Server Side Rendering

The React SDK supports server-side rendering (SSR). Pre-fetch the datafile and pass it to createInstance so decisions are available synchronously. Server-side instances are short-lived (created per request), so configure them to avoid unnecessary background work:

import { createInstance, OptimizelyProvider, OptimizelyDecideOption, useDecision } from '@optimizely/react-sdk';

function App() {
  const isServerSide = typeof window === 'undefined';
  const [optimizely] = useState(() =>
    createInstance({
      datafile,
      sdkKey: process.env.NEXT_PUBLIC_OPTIMIZELY_SDK_KEY || '',
      datafileOptions: { autoUpdate: !isServerSide },
      defaultDecideOptions: isServerSide ? [OptimizelyDecideOption.DISABLE_DECISION_EVENT] : [],
      odpOptions: {
        disabled: isServerSide,
      },
    })
  );
}

function MyComponent() {
  const [decision] = useDecision('flag1');
  return decision.enabled ? <p>Feature enabled</p> : <p>Feature disabled</p>;
}

<OptimizelyProvider optimizely={optimizelyClient} user={{ id: 'user1' }} isServerSide={isServerSide}>
  <MyComponent />
</OptimizelyProvider>;

| Option | Server value | Why | | ---------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------ | | datafile | Pre-fetched datafile JSON | Provides the datafile directly so the SDK is ready synchronously to make decisions | | datafileOptions.autoUpdate | false | No need to poll for datafile updates on a per-request instance | | defaultDecideOptions | [DISABLE_DECISION_EVENT] | avoids duplicate decision events if the client will also fire them after hydration | | odpOptions.disabled | true | Disables ODP event manager processing during SSR — avoids unnecessary event batching, API calls, and VUID tracking overhead |

ODP audience segments during SSR: Disabling ODP prevents automatic segment fetching, but you can still make audience-segment-based decisions by passing pre-fetched segments via the qualifiedSegments prop on OptimizelyProvider.

getQualifiedSegments

A standalone async utility that fetches qualified ODP audience segments for a user, given a datafile. It parses the datafile to extract ODP configuration and segment conditions, queries the ODP GraphQL API, and returns only the segments where the user is qualified.

import { getQualifiedSegments } from '@optimizely/react-sdk';

const segments = await getQualifiedSegments(userId, datafile);

| Argument | Type | Description | | ---------- | --------------------------------- | ------------------------------------------------ | | userId | string | The user ID to fetch qualified segments for | | datafile | string \| Record<string, any> | The Optimizely datafile (JSON object or string) |

Returns: Promise<string[] | null>

Caching recommendation: The ODP segment fetch adds latency to server rendering. Consider caching the result per user to avoid re-fetching on every request.

React Server Components (v3.4.0+)

Since version 3.4.0, the SDK can be used directly in React Server Components without OptimizelyProvider. Create an instance, set the user, wait for readiness, and make decisions — all within an async server component:

import { createInstance } from '@optimizely/react-sdk';

export default async function ServerExperiment() {
  const client = createInstance({
    sdkKey: process.env.OPTIMIZELY_SDK_KEY || '',
  });

  client.setUser({
    id: 'user-123',
  });

  await client.onReady();

  const decision = client.decide('flag-1');

  client.close();

  return decision.enabled ? <h1>Experiment Variation</h1> : <h1>Control</h1>;
}

Next.js Integration

For detailed Next.js examples covering both App Router and Pages Router patterns, see the Next.js Integration Guide.

Limitations

  • Datafile required — SSR requires a pre-fetched datafile. Using sdkKey alone falls back to a failed decision.
  • User Promise not supported — User Promise is not supported during SSR.
  • ODP segments — ODP audience segments require async I/O and are not available during server rendering. Use getQualifiedSegments to pre-fetch segments server-side and pass them via the qualifiedSegments prop on OptimizelyProvider to enable synchronous ODP-based decisions. Without it, consider deferring the decision to the client using the fallback pattern.

For more details and workarounds, see the Next.js Integration Guide — Limitations.

Disabled event dispatcher

To disable sending all events to Optimizely's results backend, use the logOnlyEventDispatcher when creating a client:

import { createInstance, logOnlyEventDispatcher } from '@optimizely/react-sdk';

const optimizely = createInstance({
  datafile: window.optimizelyDatafile,
  eventDispatcher: logOnlyEventDispatcher,
});

Additional code

This repository includes the following third party open source code:

hoist-non-react-statics Copyright © 2015 Yahoo!, Inc. License: BSD

js-tokens Copyright © 2014, 2015, 2016, 2017, 2018, 2019 Simon Lydell License: MIT

json-schema Copyright © 2005-2015, The Dojo Foundation License: BSD

lodash Copyright © JS Foundation and other contributors License: MIT

loose-envify Copyright © 2015 Andres Suarez [email protected] License: MIT

node-murmurhash Copyright © 2012 Gary Court, Derek Perez License: MIT

object-assign Copyright © Sindre Sorhus (sindresorhus.com) License: MIT

promise-polyfill Copyright © 2014 Taylor Hakes Copyright © 2014 Forbes Lindesay License: MIT

react-is Copyright © Facebook, Inc. and its affiliates. License: MIT

react Copyright © Facebook, Inc. and its affiliates. License: MIT

scheduler Copyright © Facebook, Inc. and its affiliates. License: MIT

node-uuid Copyright © 2010-2016 Robert Kieffer and other contributors License: MIT

To regenerate the dependencies use by this package, run the following command:

npx license-checker --production --json | jq 'map_values({ licenses, publisher, repository }) | del(.[][] | nulls)'

Contributing

Please see CONTRIBUTING for more information.

Credits

First-party code subject to copyrights held by Optimizely, Inc. and its contributors and licensed to you under the terms of the Apache 2.0 license.

Other Optimizely SDKs

  • Agent - https://github.com/optimizely/agent

  • Android - https://github.com/optimizely/android-sdk

  • C# - https://github.com/optimizely/csharp-sdk

  • Flutter - https://github.com/optimizely/optimizely-flutter-sdk

  • Go - https://github.com/optimizely/go-sdk

  • Java - https://github.com/optimizely/java-sdk

  • JavaScript - https://github.com/optimizely/javascript-sdk

  • PHP - https://github.com/optimizely/php-sdk

  • Python - https://github.com/optimizely/python-sdk

  • Ruby - https://github.com/optimizely/ruby-sdk

  • Swift - https://github.com/optimizely/swift-sdk