Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
2.6.0 (October 31, 2025)
2.6.0 (November 4, 2025)
- Added `useTreatment`, `useTreatments`, `useTreatmentWithConfig` and `useTreatmentsWithConfig` hooks to replace the now deprecated `useSplitTreatments` hook.
- Updated @splitsoftware/splitio package to version 11.8.0 that includes minor updates:
- Added new configuration for Fallback Treatments, which allows setting a treatment value and optional config to be returned in place of "control", either globally or by flag. Read more in our docs.
- Added support for custom loggers: added `logger` configuration option and `factory.Logger.setLogger` method to allow the SDK to use a custom logger.
Expand Down
35 changes: 29 additions & 6 deletions MIGRATION-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,32 @@

React SDK v2.0.0 has a few breaking changes that you should consider when migrating from a previous version. The main changes are:

### • Deprecated `useClient`, `useTreatments`, and `useManager` hooks have been removed.

Follow [this section](#migrating-to-get-react-sdk-v1100-improvements-replacing-the-deprecated-useclient-usetreatments-and-usemanager-hooks) to migrate to the new hooks `useSplitClient`, `useSplitTreatments`, and `useSplitManager`.
### • `useTreatments` hook was removed in v2.0.0, but re-introduced in v2.6.0 with a different API:

Since v2.6.0, there are 4 hooks variants to evaluate feature flags, to better cover the different evaluation methods available in the JavaScript SDK client:

- `useTreatment`: returns a treatment value for a given feature flag name. It calls `client.getTreatment()` method under the hood.
- `useTreatmentWithConfig`: returns a treatment value and its configuration for a given feature flag name. It calls `client.getTreatmentWithConfig()` method under the hood.
- `useTreatments`: returns an object with treatment values for multiple feature flag names. It calls `client.getTreatments()` or `client.getTreatmentsByFlagSets()` methods under the hood, depending if the `names` or `flagSets` option is provided.
- `useTreatmentsWithConfig`: returns an object with treatment values and their configurations for multiple feature flag names. It calls `client.getTreatmentsWithConfig()` or `client.getTreatmentsWithConfigByFlagSets()` methods under the hood, depending if the `names` or `flagSets` option is provided.

The `useTreatments` hook from v1.x.x should be replaced with `useTreatmentsWithConfig`, as follows:

```javascript
// v1.x.x
const treatments = useTreatments(featureFlagNames, optionalAttributes, optionalSplitKey);

// v2.6.0+
const { treatments } = useTreatmentsWithConfig({ names: featureFlagNames, attributes: optionalAttributes, splitKey: optionalSplitKey });

// v2.0.0-v2.5.0
const { treatments } = useSplitTreatments({ names: featureFlagNames, attributes: optionalAttributes, splitKey: optionalSplitKey });
```

### • Deprecated `useClient` and `useManager` hooks have been removed.

Follow [this section](#migrating-to-get-react-sdk-v1100-improvements-replacing-the-deprecated-useclient-usetreatments-and-usemanager-hooks) to migrate to the new hooks `useSplitClient` and `useSplitManager`.

### • Updated the default value of `updateOnSdkUpdate` and `updateOnSdkTimedout` options to `true`.

Expand All @@ -15,7 +38,7 @@ Consider setting the `updateOnSdkUpdate` option to `false` to revert to the prev

The same applies for the equivalent props in the `[with]SplitClient` and `[with]SplitTreatments` components, although these components are deprecated and we recommend [migrating to their hook alternatives](#-high-order-components-withsplitclient-withsplittreatments-and-components-that-accept-a-render-function-as-child-component-splittreatments-and-splitclient-have-been-deprecated-and-might-be-removed-in-a-future-major-release).

### • Deprecated `SplitFactory` provider has been removed, `withSplitFactory` is deprecated, and `SplitFactoryProvider` doesn't accept `updateOn` props and a render function as children anymore.
### • Deprecated `SplitFactory` provider has been removed, `withSplitFactory` is deprecated, and `SplitFactoryProvider` doesn't accept a render function as children anymore.

To migrate your existing code to the new version of `SplitFactoryProvider`, consider the following refactor example:

Expand Down Expand Up @@ -53,21 +76,21 @@ should be refactored to:

```tsx
const MyComponent = () => {
const props: ISplitContextValues = useSplitClient({ updateOnSdkUpdate: false });
const props: ISplitContextValues = useSplitClient();
const { factory, client, isReady, isReadyFromCache, ... } = props;
...
};

const App = () => {
return (
<SplitFactoryProvider config={mySplitConfig} attributes={DEFAULT_CLIENT_ATTRIBUTES} >
<SplitFactoryProvider config={mySplitConfig} updateOnSdkUpdate={false} attributes={DEFAULT_CLIENT_ATTRIBUTES} >
<MyComponent />
</SplitFactoryProvider>
);
};
```

Notice that `MyComponent` was refactored to use the `useSplitClient` hook and is passed as a React JSX element rather than a render function. The `useSplitClient` hook is called without providing a `splitKey` param. This means that the default client (whose key is set in the `core.key` property of the `mySplitConfig` object) will be used, and the `updateOnSdkUpdate` and `attributes` props are passed as options to the hook.
Notice that `MyComponent` was refactored to use the `useSplitClient` hook and is passed as a React JSX element rather than a render function. The `useSplitClient` hook is called without providing a `splitKey` param. This means that the default client (whose key is set in the `core.key` property of the `mySplitConfig` object) will be used.

### • High-Order-Components (`withSplitClient`, `withSplitTreatments`) and components that accept a render function as child component (`SplitTreatments`, and `SplitClient`) have been deprecated and might be removed in a future major release.

Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Below is a simple example that describes the instantiation and most basic usage
import React from 'react';

// Import SDK functions
import { SplitFactoryProvider, useSplitTreatments } from '@splitsoftware/splitio-react';
import { SplitFactoryProvider, useTreatment } from '@splitsoftware/splitio-react';

// Define your config object
const CONFIG = {
Expand All @@ -29,18 +29,18 @@ const CONFIG = {
};

function MyComponent() {
// Evaluate feature flags with useSplitTreatments hook
const { treatments: { FEATURE_FLAG_NAME }, isReady } = useSplitTreatments({ names: ['FEATURE_FLAG_NAME'] });
// Evaluate a feature flag with useTreatment hook
const { treatment, isReady } = useTreatment({ name: 'FEATURE_FLAG_NAME' });

// Check SDK readiness using isReady prop
if (!isReady) return <div>Loading SDK ...</div>;

if (FEATURE_FLAG_NAME.treatment === 'on') {
// return JSX for on treatment
} else if (FEATURE_FLAG_NAME.treatment === 'off') {
// return JSX for off treatment
if (treatment === 'on') {
// return JSX for 'on' treatment
} else if (treatment === 'off') {
// return JSX for 'off' treatment
} else {
// return JSX for control treatment
// return JSX for 'control' treatment
};
}

Expand Down
46 changes: 23 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio-react",
"version": "2.5.0",
"version": "2.6.0",
"description": "A React library to easily integrate and use Split JS SDK",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down Expand Up @@ -63,7 +63,7 @@
},
"homepage": "https://github.com/splitio/react-client#readme",
"dependencies": {
"@splitsoftware/splitio": "11.7.2-rc.4",
"@splitsoftware/splitio": "11.8.0",
"memoize-one": "^5.1.1",
"shallowequal": "^1.1.0",
"tslib": "^2.3.1"
Expand Down
2 changes: 0 additions & 2 deletions src/SplitClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { useSplitClient } from './useSplitClient';
*
* The underlying SDK client can be changed during the component lifecycle
* if the component is updated with a different splitKey prop.
*
* @deprecated `SplitClient` will be removed in a future major release. We recommend replacing it with the `useSplitClient` hook.
*/
export function SplitClient(props: ISplitClientProps) {
const { children } = props;
Expand Down
2 changes: 1 addition & 1 deletion src/SplitTreatments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useSplitTreatments } from './useSplitTreatments';
* call the 'client.getTreatmentsWithConfig()' method if the `names` prop is provided, or the 'client.getTreatmentsWithConfigByFlagSets()' method
* if the `flagSets` prop is provided. It then passes the resulting treatments to a child component as a function.
*
* @deprecated `SplitTreatments` will be removed in a future major release. We recommend replacing it with the `useSplitTreatments` hook.
* @deprecated `SplitTreatments` will be removed in a future major release. We recommend replacing it with the `useTreatment*` hooks.
*/
export function SplitTreatments(props: ISplitTreatmentsProps) {
const { children } = props;
Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {
useSplitClient as exportedUseSplitClient,
useSplitTreatments as exportedUseSplitTreatments,
useSplitManager as exportedUseSplitManager,
useTreatment as exportedUseTreatment,
useTreatmentWithConfig as exportedUseTreatmentWithConfig,
useTreatments as exportedUseTreatments,
useTreatmentsWithConfig as exportedUseTreatmentsWithConfig,
// Checks that types are exported. Otherwise, the test would fail with a TS error.
GetTreatmentsOptions,
ISplitClientChildProps,
Expand Down Expand Up @@ -39,6 +43,10 @@ import { useTrack } from '../useTrack';
import { useSplitClient } from '../useSplitClient';
import { useSplitTreatments } from '../useSplitTreatments';
import { useSplitManager } from '../useSplitManager';
import { useTreatment } from '../useTreatment';
import { useTreatmentWithConfig } from '../useTreatmentWithConfig';
import { useTreatments } from '../useTreatments';
import { useTreatmentsWithConfig } from '../useTreatmentsWithConfig';

describe('index', () => {

Expand All @@ -59,6 +67,10 @@ describe('index', () => {
expect(exportedUseSplitClient).toBe(useSplitClient);
expect(exportedUseSplitTreatments).toBe(useSplitTreatments);
expect(exportedUseSplitManager).toBe(useSplitManager);
expect(exportedUseTreatment).toBe(useTreatment);
expect(exportedUseTreatmentWithConfig).toBe(useTreatmentWithConfig);
expect(exportedUseTreatments).toBe(useTreatments);
expect(exportedUseTreatmentsWithConfig).toBe(useTreatmentsWithConfig);
});

it('should export SplitContext', () => {
Expand Down
23 changes: 23 additions & 0 deletions src/__tests__/testUtils/mockSplitFactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EventEmitter } from 'events';
import jsSdkPackageJson from '@splitsoftware/splitio/package.json';
import reactSdkPackageJson from '../../../package.json';
import { CONTROL, CONTROL_WITH_CONFIG } from '../../constants';

export const jsSdkVersion = `javascript-${jsSdkPackageJson.version}`;
export const reactSdkVersion = `react-${reactSdkPackageJson.version}`;
Expand Down Expand Up @@ -65,6 +66,24 @@ export function mockSdk() {
const track: jest.Mock = jest.fn(() => {
return true;
});
const getTreatment: jest.Mock = jest.fn((featureFlagName: string) => {
return typeof featureFlagName === 'string' ? 'on' : CONTROL;
});
const getTreatments: jest.Mock = jest.fn((featureFlagNames: string[]) => {
return featureFlagNames.reduce((result: SplitIO.Treatments, featureName: string) => {
result[featureName] = 'on';
return result;
}, {});
});
const getTreatmentsByFlagSets: jest.Mock = jest.fn((flagSets: string[]) => {
return flagSets.reduce((result: SplitIO.Treatments, flagSet: string) => {
result[flagSet + '_feature_flag'] = 'on';
return result;
}, {});
});
const getTreatmentWithConfig: jest.Mock = jest.fn((featureFlagName: string) => {
return typeof featureFlagName === 'string' ? { treatment: 'on', config: null } : CONTROL_WITH_CONFIG;
});
const getTreatmentsWithConfig: jest.Mock = jest.fn((featureFlagNames: string[]) => {
return featureFlagNames.reduce((result: SplitIO.TreatmentsWithConfig, featureName: string) => {
result[featureName] = { treatment: 'on', config: null };
Expand Down Expand Up @@ -113,6 +132,10 @@ export function mockSdk() {
});

return Object.assign(Object.create(__emitter__), {
getTreatment,
getTreatments,
getTreatmentsByFlagSets,
getTreatmentWithConfig,
getTreatmentsWithConfig,
getTreatmentsWithConfigByFlagSets,
track,
Expand Down
8 changes: 8 additions & 0 deletions src/__tests__/testUtils/sdkConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ export const sdkBrowser: SplitIO.IBrowserSettings = {
key: 'customer-key',
},
};

export const sdkBrowserWithConfig: SplitIO.IBrowserSettings = {
...sdkBrowser,
fallbackTreatments: {
global: 'control_global',
byFlag: { ff1: { treatment: 'control_ff1', config: 'control_ff1_config' } }
}
};
Loading