├── .devcontainer └── devcontainer.json ├── .eslintrc.js ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── BUG-REPORT.yml │ ├── ENHANCEMENT.yml │ ├── FEATURE-REQUEST.md │ └── config.yml ├── pull_request_template.md └── workflows │ ├── integration_test.yml │ ├── react.yml │ ├── react_release.yml │ └── ticket_reference_check.yml ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierrc ├── .vscode ├── launch.json └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── scripts ├── build.js ├── config.js └── winbuild.js ├── src ├── Context.ts ├── Experiment.spec.tsx ├── Experiment.tsx ├── Feature.spec.tsx ├── Feature.tsx ├── Provider.spec.tsx ├── Provider.tsx ├── Variation.tsx ├── autoUpdate.ts ├── client.spec.ts ├── client.ts ├── hooks.spec.tsx ├── hooks.ts ├── index.cjs.ts ├── index.ts ├── logOnlyEventDispatcher.spec.ts ├── logOnlyEventDispatcher.ts ├── logger.spec.ts ├── logger.tsx ├── notifier.spec.ts ├── notifier.ts ├── utils.spec.tsx ├── utils.tsx ├── withOptimizely.spec.tsx └── withOptimizely.tsx ├── srcclr.yml ├── tsconfig.json └── yarn.lock /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React SDK", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye", 4 | "postCreateCommand": "npm i -g yarn@1.22.22 && yarn install", 5 | "customizations": { 6 | "vscode": { 7 | "extensions": [ 8 | "dbaeumer.vscode-eslint", 9 | "eamodio.gitlens", 10 | "esbenp.prettier-vscode", 11 | "Gruntfuggly.todo-tree", 12 | "github.vscode-github-actions", 13 | "Orta.vscode-jest", 14 | "ms-vscode.test-adapter-converter", 15 | "GitHub.copilot-chat", 16 | "vivaxy.vscode-conventional-commits" 17 | ], 18 | "settings": { 19 | "files.eol": "\n" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserOptions: { 3 | ecmaFeatures: { 4 | jsx: true, 5 | }, 6 | ecmaVersion: 2015, 7 | sourceType: 'module', 8 | }, 9 | env: { 10 | browser: true, 11 | es6: true, 12 | jest: true, 13 | mocha: true, 14 | node: true, 15 | }, 16 | extends: [ 17 | 'plugin:react-hooks/recommended', 18 | 'eslint:recommended', 19 | 'plugin:@typescript-eslint/recommended', 20 | 'plugin:prettier/recommended', 21 | ], 22 | rules: { 23 | '@typescript-eslint/ban-ts-comment': 'warn', 24 | '@typescript-eslint/camelcase': 'off', 25 | '@typescript-eslint/no-empty-function': 'off', 26 | '@typescript-eslint/no-shadow': 'error', 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG-REPORT.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug 2 | description: File a bug/issue 3 | title: "[BUG]
250 | Click to login 251 |
252 | ); 253 | } 254 | ``` 255 | 256 | ## `withOptimizely` 257 | 258 | Any component under the `My feature is enabled
} 325 | { !decision.enabled &&My feature is disabled
} 326 | { decision.variationKey === 'control-variation' &&Current Variation
} 327 | { decision.variationKey === 'experimental-variation' &&Better Variation
} 328 | 329 | > 330 | ); 331 | } 332 | ``` 333 | 334 | ### Tracking 335 | Use the built-in `useTrackEvent` hook to access the `track` method of optimizely instance 336 | 337 | ```jsx 338 | import { useTrackEvent } from '@optimizely/react-sdk'; 339 | 340 | function SignupButton() { 341 | const [track, clientReady, didTimeout] = useTrackEvent() 342 | 343 | const handleClick = () => { 344 | if(clientReady) { 345 | track('signup-clicked') 346 | } 347 | } 348 | 349 | return ( 350 | 351 | ) 352 | } 353 | ``` 354 | 355 | Or you can use the `withOptimizely` HoC. 356 | 357 | ```jsx 358 | import { withOptimizely } from '@optimizely/react-sdk'; 359 | 360 | class SignupButton extends React.Component { 361 | onClick = () => { 362 | const { optimizely } = this.props; 363 | optimizely.track('signup-clicked'); 364 | // rest of click handler 365 | }; 366 | 367 | render() { 368 | ; 369 | } 370 | } 371 | 372 | const WrappedSignupButton = withOptimizely(SignupButton); 373 | ``` 374 | 375 | **_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`. 376 | 377 | ## `ReactSDKClient` 378 | 379 | The following type definitions are used in the `ReactSDKClient` interface: 380 | 381 | - `UserAttributes : { [name: string]: any }` 382 | - `User : { id: string | null, attributes: userAttributes }` 383 | - `VariableValuesObject : { [key: string]: any }` 384 | - `EventTags : { [key: string]: string | number | boolean; }` 385 | 386 | `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](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/welcome). 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. 387 | 388 | - `onReady(opts?: { timeout?: number }): PromiseThe feature is enabled
} 454 | { !decision.enabled &&The feature is not enabled
} 455 | { decision.variationKey === 'variation1' &&Variation 1
} 456 | { decision.variationKey === 'variation2' &&Variation 2
} 457 |,
60 | Source: React.ComponentType = Omit ;
29 |
30 | export function withOptimizely (
31 | Component: React.ComponentType
32 | ): React.ForwardRefExoticComponent & { forwardedRef?: React.Ref