React-SDK - 4.0.0

[4.0.0] - May 18, 2026

v4 is a ground-up rewrite of the React SDK. For a detailed upgrade guide, see MIGRATION.md. For the official documentation, see the React SDK Developer Docs.

New Features

  • New hook APIuseDecide, useDecideForKeys, useDecideAll replace the old useDecision, useExperiment, and useFeature hooks. Return type changed from positional tuples ([decision, clientReady, didTimeout]) to discriminated union objects ({ decision, isLoading, error }).
  • Async decision hooksuseDecideAsync, useDecideForKeysAsync, useDecideAllAsync for use with CMAB (Contextual Multi-Armed Bandit) experiments and async User Profile Service lookups.
  • useOptimizelyClient hook — Access the Optimizely Client instance directly (replaces withOptimizely HOC).
  • useOptimizelyUserContext hook — Access the current OptimizelyUserContext, with { userContext, isLoading, error } return type. Use for event tracking and forced decisions.
  • Modular client configurationcreateInstance now accepts dedicated factory-created components (createPollingProjectConfigManager, createStaticProjectConfigManager, createBatchEventProcessor, createForwardingEventProcessor, createOdpManager, createVuidManager, createErrorNotifier, createLogger) for granular control and smaller bundles.
  • CMAB support — Contextual Multi-Armed Bandit experiments via async decide hooks (useDecideAsync). New decide options: IGNORE_CMAB_CACHE, RESET_CMAB_CACHE, INVALIDATE_USER_CMAB_CACHE.
  • Holdouts support — Holdouts Feature Experimentation capability.
  • Feature Rollouts — A new experiment type combining Targeted Delivery simplicity with A/B test measurement capabilities, including full impact analytics and metric tracking.
  • Async User Profile Service — Support for asynchronous user profile service lookups.
  • getSendBeaconEventDispatcher export — New event dispatcher using the Beacon API for reliable event delivery on page unload.

Breaking Changes

  • Underlying JS SDK upgraded from v5 to v6 — See the JavaScript SDK v6 Migration Guide for details.
  • ESM only — No CommonJS entry point. Projects using require() must switch to ESM imports or configure their bundler.
  • Node.js >=18.0.0 required (was >=14.0.0).
  • Provider prop renamedoptimizelyclient.
  • Provider user prop no longer accepts a Promise — Resolve the user before rendering.
  • Removed Provider propsisServerSide, userId, userAttributes.
  • Default timeout changed — From 5000 ms to 30000 ms.
  • onReady() behavior changed — Resolves on success, rejects on failure (no longer returns { success, reason }).
  • createInstance throws on invalid config (previously returned null).
  • Event processing, ODP, VUID, and logging are opt-in — Must be explicitly enabled via factory functions.
  • Removed componentsOptimizelyExperiment, OptimizelyFeature, OptimizelyVariation.
  • Removed HOCwithOptimizely.
  • Removed hooksuseDecision (renamed to useDecide), useExperiment, useFeature, useTrackEvent.
  • Removed per-hook autoUpdate option — Hooks now automatically re-evaluate on datafile polling updates. No opt-in needed.
  • Removed per-hook overrideUserId / overrideAttributes — Use separate <OptimizelyProvider> instances for different users instead.
  • Removed exportsReactSDKClient, OptimizelyContext, setLogger, setLogLevel, logOnlyEventDispatcher, enums, logging, errorHandler.
  • createLogger replaces setLogger/setLogLevel — Logging disabled by default; pass createLogger({ logLevel }) to createInstance.
  • getQualifiedSegments return type changed — Now returns { segments, error } instead of string[] | null.

Changed

  • Null/undefined user behavior — Provider now accepts user={null} in addition to undefined. When no user is provided, hooks return { isLoading: true } instead of attempting to create a user context.


https://github.com/optimizely/react-sdk/releases/tag/4.0.0