Skip to content

Commit b93c313

Browse files
Merge pull request #253 from splitio/development
Release v2.6.0
2 parents ccc26d6 + 6fa03ad commit b93c313

35 files changed

+1235
-321
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2.6.0 (November 4, 2025)
2+
- Added `useTreatment`, `useTreatments`, `useTreatmentWithConfig` and `useTreatmentsWithConfig` hooks to replace the now deprecated `useSplitTreatments` hook.
3+
- Updated @splitsoftware/splitio package to version 11.8.0 that includes minor updates:
4+
- 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.
5+
- Added support for custom loggers: added `logger` configuration option and `factory.Logger.setLogger` method to allow the SDK to use a custom logger.
6+
- Updated the SDK_READY_FROM_CACHE event to be emitted alongside the SDK_READY event if it hasn’t already been emitted.
7+
18
2.5.0 (September 18, 2025)
29
- Updated @splitsoftware/splitio package to version 11.6.0 that includes minor updates:
310
- Added `storage.wrapper` configuration option to allow the SDK to use a custom storage wrapper for the storage type `LOCALSTORAGE`. Default value is `window.localStorage`.

MIGRATION-GUIDE.md

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,32 @@
33

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

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

8-
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`.
7+
### `useTreatments` hook was removed in v2.0.0, but re-introduced in v2.6.0 with a different API:
8+
9+
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:
10+
11+
- `useTreatment`: returns a treatment value for a given feature flag name. It calls `client.getTreatment()` method under the hood.
12+
- `useTreatmentWithConfig`: returns a treatment value and its configuration for a given feature flag name. It calls `client.getTreatmentWithConfig()` method under the hood.
13+
- `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.
14+
- `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.
15+
16+
The `useTreatments` hook from v1.x.x should be replaced with `useTreatmentsWithConfig`, as follows:
17+
18+
```javascript
19+
// v1.x.x
20+
const treatments = useTreatments(featureFlagNames, optionalAttributes, optionalSplitKey);
21+
22+
// v2.6.0+
23+
const { treatments } = useTreatmentsWithConfig({ names: featureFlagNames, attributes: optionalAttributes, splitKey: optionalSplitKey });
24+
25+
// v2.0.0-v2.5.0
26+
const { treatments } = useSplitTreatments({ names: featureFlagNames, attributes: optionalAttributes, splitKey: optionalSplitKey });
27+
```
28+
29+
### • Deprecated `useClient` and `useManager` hooks have been removed.
30+
31+
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`.
932

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

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

1639
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).
1740

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

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

@@ -53,21 +76,21 @@ should be refactored to:
5376

5477
```tsx
5578
const MyComponent = () => {
56-
const props: ISplitContextValues = useSplitClient({ updateOnSdkUpdate: false });
79+
const props: ISplitContextValues = useSplitClient();
5780
const { factory, client, isReady, isReadyFromCache, ... } = props;
5881
...
5982
};
6083

6184
const App = () => {
6285
return (
63-
<SplitFactoryProvider config={mySplitConfig} attributes={DEFAULT_CLIENT_ATTRIBUTES} >
86+
<SplitFactoryProvider config={mySplitConfig} updateOnSdkUpdate={false} attributes={DEFAULT_CLIENT_ATTRIBUTES} >
6487
<MyComponent />
6588
</SplitFactoryProvider>
6689
);
6790
};
6891
```
6992

70-
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.
93+
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.
7194

7295
### • 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.
7396

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Below is a simple example that describes the instantiation and most basic usage
1818
import React from 'react';
1919

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

2323
// Define your config object
2424
const CONFIG = {
@@ -29,18 +29,18 @@ const CONFIG = {
2929
};
3030

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

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

38-
if (FEATURE_FLAG_NAME.treatment === 'on') {
39-
// return JSX for on treatment
40-
} else if (FEATURE_FLAG_NAME.treatment === 'off') {
41-
// return JSX for off treatment
38+
if (treatment === 'on') {
39+
// return JSX for 'on' treatment
40+
} else if (treatment === 'off') {
41+
// return JSX for 'off' treatment
4242
} else {
43-
// return JSX for control treatment
43+
// return JSX for 'control' treatment
4444
};
4545
}
4646

package-lock.json

Lines changed: 23 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-react",
3-
"version": "2.5.0",
3+
"version": "2.6.0",
44
"description": "A React library to easily integrate and use Split JS SDK",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",
@@ -63,7 +63,7 @@
6363
},
6464
"homepage": "https://github.com/splitio/react-client#readme",
6565
"dependencies": {
66-
"@splitsoftware/splitio": "11.6.0",
66+
"@splitsoftware/splitio": "11.8.0",
6767
"memoize-one": "^5.1.1",
6868
"shallowequal": "^1.1.0",
6969
"tslib": "^2.3.1"

src/SplitClient.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { useSplitClient } from './useSplitClient';
99
*
1010
* The underlying SDK client can be changed during the component lifecycle
1111
* if the component is updated with a different splitKey prop.
12-
*
13-
* @deprecated `SplitClient` will be removed in a future major release. We recommend replacing it with the `useSplitClient` hook.
1412
*/
1513
export function SplitClient(props: ISplitClientProps) {
1614
const { children } = props;

src/SplitFactoryProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function SplitFactoryProvider(props: ISplitFactoryProviderProps) {
5151
// Effect to initialize and destroy the factory when config is provided
5252
React.useEffect(() => {
5353
if (propFactory) {
54-
if (config) console.log(WARN_SF_CONFIG_AND_FACTORY);
54+
if (config) (propFactory.settings as any).log.warn(WARN_SF_CONFIG_AND_FACTORY);
5555
return;
5656
}
5757

src/SplitTreatments.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useSplitTreatments } from './useSplitTreatments';
99
* call the 'client.getTreatmentsWithConfig()' method if the `names` prop is provided, or the 'client.getTreatmentsWithConfigByFlagSets()' method
1010
* if the `flagSets` prop is provided. It then passes the resulting treatments to a child component as a function.
1111
*
12-
* @deprecated `SplitTreatments` will be removed in a future major release. We recommend replacing it with the `useSplitTreatments` hook.
12+
* @deprecated `SplitTreatments` will be removed in a future major release. We recommend replacing it with the `useTreatment*` hooks.
1313
*/
1414
export function SplitTreatments(props: ISplitTreatmentsProps) {
1515
const { children } = props;

src/__tests__/SplitClient.test.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe('SplitClient', () => {
5656
client: outerFactory.client(),
5757
isReady: true,
5858
isReadyFromCache: true,
59+
isOperational: true,
5960
lastUpdate: getStatus(outerFactory.client()).lastUpdate
6061
});
6162

@@ -141,7 +142,7 @@ describe('SplitClient', () => {
141142
expect(statusProps).toStrictEqual([false, false, true, true]);
142143
break;
143144
case 2: // Updated. Although `updateOnSdkReady` is false, status props must reflect the current status of the client.
144-
expect(statusProps).toStrictEqual([true, false, true, false]);
145+
expect(statusProps).toStrictEqual([true, true, true, false]);
145146
break;
146147
default:
147148
fail('Child must not be rerendered');
@@ -182,7 +183,7 @@ describe('SplitClient', () => {
182183
expect(statusProps).toStrictEqual([false, false, false, false]);
183184
break;
184185
case 1: // Ready
185-
expect(statusProps).toStrictEqual([true, false, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
186+
expect(statusProps).toStrictEqual([true, true, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
186187
break;
187188
default:
188189
fail('Child must not be rerendered');
@@ -214,7 +215,7 @@ describe('SplitClient', () => {
214215
count++;
215216

216217
// side effect in the render phase
217-
if (!(client as any).__getStatus().isReady) {
218+
if (!client!.getStatus().isReady) {
218219
(client as any).__emitter__.emit(Event.SDK_READY);
219220
}
220221

@@ -318,11 +319,11 @@ describe('SplitClient', () => {
318319
break;
319320
case 4:
320321
expect(client).toBe(outerFactory.client('user3'));
321-
expect(statusProps).toStrictEqual([true, false, false, false]);
322+
expect(statusProps).toStrictEqual([true, true, false, false]);
322323
break;
323324
case 5:
324325
expect(client).toBe(outerFactory.client('user3'));
325-
expect(statusProps).toStrictEqual([true, false, false, false]);
326+
expect(statusProps).toStrictEqual([true, true, false, false]);
326327
break;
327328
default:
328329
fail('Child must not be rerendered');
@@ -501,7 +502,7 @@ describe('SplitFactoryProvider + SplitClient', () => {
501502
expect(statusProps).toStrictEqual([false, false, true, true]);
502503
break;
503504
case 2: // Updated. Although `updateOnSdkReady` is false, status props must reflect the current status of the client.
504-
expect(statusProps).toStrictEqual([true, false, true, false]);
505+
expect(statusProps).toStrictEqual([true, true, true, false]);
505506
break;
506507
default:
507508
fail('Child must not be rerendered');
@@ -542,7 +543,7 @@ describe('SplitFactoryProvider + SplitClient', () => {
542543
expect(statusProps).toStrictEqual([false, false, true, true]);
543544
break;
544545
case 2: // Updated. Although `updateOnSdkReady` is false, status props must reflect the current status of the client.
545-
expect(statusProps).toStrictEqual([true, false, true, false]);
546+
expect(statusProps).toStrictEqual([true, true, true, false]);
546547
break;
547548
default:
548549
fail('Child must not be rerendered');
@@ -578,7 +579,7 @@ describe('SplitFactoryProvider + SplitClient', () => {
578579
expect(statusProps).toStrictEqual([false, false, false, false]);
579580
break;
580581
case 1: // Ready
581-
expect(statusProps).toStrictEqual([true, false, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
582+
expect(statusProps).toStrictEqual([true, true, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
582583
break;
583584
default:
584585
fail('Child must not be rerendered');
@@ -615,7 +616,7 @@ describe('SplitFactoryProvider + SplitClient', () => {
615616
expect(statusProps).toStrictEqual([false, false, false, false]);
616617
break;
617618
case 1: // Ready
618-
expect(statusProps).toStrictEqual([true, false, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
619+
expect(statusProps).toStrictEqual([true, true, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state
619620
break;
620621
default:
621622
fail('Child must not be rerendered');

src/__tests__/SplitFactoryProvider.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ describe('SplitFactoryProvider', () => {
7070
client: outerFactory.client(),
7171
isReady: true,
7272
isReadyFromCache: true,
73+
isOperational: true,
7374
lastUpdate: getStatus(outerFactory.client()).lastUpdate
7475
});
7576
return null;
@@ -113,7 +114,7 @@ describe('SplitFactoryProvider', () => {
113114
</SplitFactoryProvider>
114115
);
115116

116-
expect(logSpy).toBeCalledWith(WARN_SF_CONFIG_AND_FACTORY);
117+
expect(logSpy).toBeCalledWith('[WARN] splitio => ' + WARN_SF_CONFIG_AND_FACTORY);
117118
logSpy.mockRestore();
118119
});
119120

0 commit comments

Comments
 (0)