diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3870a1f..57bc60a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -27,7 +27,7 @@ jobs: with: fetch-depth: 0 - - name: Set up nodejs + - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: 'lts/*' diff --git a/CHANGES.txt b/CHANGES.txt index 484690e..2f76f56 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,9 +5,10 @@ - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for ECMAScript Modules build. - Bugfixing - When the `config` prop is provided, the `SplitFactoryProvider` now makes the SDK factory and client instances available in the context immediately during the initial render, instead of waiting for the first SDK event (Related to https://github.com/splitio/react-client/issues/198). This change fixes a bug in the `useTrack` hook, which was not retrieving the client's `track` method during the initial render. - BREAKING CHANGES: + - NOTE: Refer to ./MIGRATION-GUIDE.md for instructions on how to migrate your codebase from version 1.x to 2.0.0. - Updated the default value of the `updateOnSdkUpdate` and `updateOnSdkTimedout` parameters of the `useSplitClient` and `useSplitTreatments` hooks options object to `true`, to re-render on all SDK events by default. The same applies for the equivalent props in the `[with]SplitClient` and `[with]SplitTreatments` components. - Updated error handling: using the library modules without wrapping them in a `SplitFactoryProvider` component will now throw an error instead of logging it, as the modules requires the `SplitContext` to work properly. - - Updated the `SplitFactoryProvider` component to not accept a child as a function (render prop), to avoid unnecessary re-renders when using the library hooks. Refer to ./MIGRATION-GUIDE.md for instructions on how to migrate the child as a function to a regular component. + - Updated the `SplitFactoryProvider` component to not accept a child as a function (render prop), to avoid unnecessary re-renders when using the library hooks. Refer to ./MIGRATION-GUIDE.md for instructions on how to migrate your component to be passed as a regular React JSX element if you were using this pattern. - Removed the `core.trafficType` option from the SDK configuration object, and the `trafficType` parameter from the SDK `client()` method, `useSplitClient`, `useTrack`, `withSplitClient` and `SplitClient` component. This is because traffic types can no longer be bound to SDK clients in JavaScript SDK v11.0.0, and so the traffic type must be provided as first argument in the `track` method calls. - Removed deprecated modules: `SplitFactory` component, `useClient`, `useTreatments` and `useManager` hooks. Refer to ./MIGRATION-GUIDE.md for instructions on how to migrate to the new alternatives. - Renamed `SplitSdk` to `SplitFactory` function, which is the underlying Split SDK factory, i.e., `import { SplitFactory } from '@splitsoftware/splitio'`. diff --git a/MIGRATION-GUIDE.md b/MIGRATION-GUIDE.md index 36932cd..df9bce4 100644 --- a/MIGRATION-GUIDE.md +++ b/MIGRATION-GUIDE.md @@ -1,4 +1,260 @@ +# Migrating to React SDK v2.0.0 + +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`. + +### • Deprecated `SplitFactory` provider has been removed, `withSplitFactory` is deprecated, and `SplitFactoryProvider` doesn't accept `updateOn` props and a render function as children anymore. + +To migrate your existing code to the new version of `SplitFactoryProvider`, consider the following refactor example: + +```tsx +const MyComponent = (props: ISplitContextValues) => { + const { factory, client, isReady, isReadyFromCache, ... } = props; + ... +}; + +// if using SplitFactoryProvider v1.11.0 +const App = () => { + return ( + + {MyComponent} + + ); +}; + +// or SplitFactory +const App = () => { + return ( + + {MyComponent} + + ); +}; + +// or withSplitFactory +const App = withSplitFactory(mySplitConfig, undefined, DEFAULT_CLIENT_ATTRIBUTES)( + MyComponent, false /* updateOnSdkUpdate = false */ +); +``` + +should be refactored to: + +```tsx +const MyComponent = () => { + const props: ISplitContextValues = useSplitClient({ updateOnSdkUpdate: false }); + const { factory, client, isReady, isReadyFromCache, ... } = props; + ... +}; + +const App = () => { + return ( + + + + ); +}; +``` + +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 `updateOn` and `attributes` props are passed as options to the hook. + +### • 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. + +The deprecation is intended to simplify the API and discourage using old patterns (HOCs and render props) in favor of the *hook* alternatives, to take advantage of React optimizations. + +To migrate your existing code based on `withSplitClient` or `SplitClient`, consider the following refactor using the `useSplitClient` hook: + +```tsx +const MyComponent = (props: ISplitContextValues) => { + const { client, isReady, ... } = props; + ... +}; + +const App = withSplitFactory(mySplitConfig)( + withSplitClient(OTHER_KEY, OTHER_KEY_ATTRIBUTES)( + MyComponent, undefined, undefined, undefined, false /* updateOnSdkReadyFromCache = false */ + ) +); + +// or +const App = () => { + return ( + + + {MyComponent} + + + ) +}; +``` + +should be refactored to: + +```tsx +const MyComponent = () => { + const props: ISplitContextValues = useSplitClient({ splitKey: OTHER_KEY, attributes: OTHER_KEY_ATTRIBUTES, updateOnSdkReadyFromCache: false }); + const { client, isReady, ... } = props; + ... +}; + +const App = () => { + return ( + + + + ) +}; +``` + +To migrate your existing code based on `withSplitTreatments` or `SplitTreatments`, consider the following refactor using the `useSplitTreatments` hook: + +```tsx +const MyComponent = (props: ISplitTreatmentsChildProps) => { + const { treatments, isReady, ... } = props; + ... +}; + +const App = withSplitFactory(mySplitConfig)( + withSplitClient(OTHER_KEY)( + withSplitTreatments(FEATURE_FLAG_NAMES, ATTRIBUTES)( + MyComponent + ) + ) +); + +// or +const App = () => { + return ( + + + + {MyComponent} + + + + ) +}; +``` + +should be refactored to: + +```tsx +const MyComponent = () => { + const props: ISplitTreatmentsChildProps = useSplitTreatments({ splitKey: OTHER_KEY, names: FEATURE_FLAG_NAMES, attributes: ATTRIBUTES }); + const { treatments, isReady, ... } = props; + ... +}; + +const App = () => { + return ( + + + + ) +}; +``` + +### • Renamed `SplitSdk` function to `SplitFactory`. + +If you are using the `SplitSdk` function to create a factory and pass it to the `SplitFactoryProvider` component, you should rename it to `SplitFactory`. For example: + +```tsx +import { SplitSdk, SplitFactoryProvider } from '@splitsoftware/splitio-react'; + +const myFactory = SplitSdk(mySplitConfig); + +const App = () => { + return ( + + + + ); +}; +``` + +should be refactored to: + +```tsx +import { SplitFactory, SplitFactoryProvider } from '@splitsoftware/splitio-react'; + +const myFactory = SplitFactory(mySplitConfig); + +const App = () => { + return ( + + + + ); +}; +``` + +### • Traffic type cannot be bound to SDK clients anymore. + +If you were passing the `trafficType` to the SDK config, `useSplitClient` hook, or `useTrack` hook, you should remove it. The `trafficType` must now be passed as the first argument of the `track` method. For example: + +```tsx +const mySplitConfig = { + core: { + authorizationKey: YOUR_CLIENT_SIDE_SDK_KEY, + key: USER_KEY, + trafficType: 'user' + } +} + +const MyComponent = () => { + const track = useTrack(); + const accountTrack = useTrack(ACCOUNT_KEY, 'account'); + + useEffect(() => { + track('my_event'); + accountTrack('my_event'); + }, []); + + ... +}; + +const App = () => { + return ( + + + + ) +}; +``` + +should be refactored to: + +```tsx +const mySplitConfig = { + core: { + authorizationKey: YOUR_CLIENT_SIDE_SDK_KEY, + key: USER_KEY + } +} + +const MyComponent = () => { + const track = useTrack(); + const accountTrack = useTrack(ACCOUNT_KEY); + + useEffect(() => { + track('user', 'my_event'); + accountTrack('account', 'my_event'); + }, []); + ... +}; + +const App = () => { + return ( + + + + ) +}; +``` + # Migrating to get React SDK v1.11.0 improvements: Replacing the deprecated `SplitFactory` and `withSplitFactory` components Starting from React SDK v1.11.0, the `SplitFactoryProvider` component is available and can replace the older `SplitFactory` and `withSplitFactory` components. The deprecated components will continue working, until they are removed in a future major release. diff --git a/README.md b/README.md index 3937848..8c11056 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ This SDK is designed to work with Split, the platform for controlled rollouts, w ## Compatibility -This SDK is compatible with React 16.3.0 and above, since it uses [React Context API](https://reactjs.org/docs/context.html). - -Some features, such as `useSplitClient` and `useSplitTreatments`, use [React Hooks API](https://reactjs.org/docs/hooks-overview.html) that requires React 16.8.0 or later. +This SDK is compatible with React 16.8.0 and above, since it uses [React Hooks API](https://react.dev/reference/react/hooks) introduced in that version. ## Getting started Below is a simple example that describes the instantiation and most basic usage of our SDK: @@ -85,7 +83,7 @@ Split has built and maintains SDKs for: * Java [Github](https://github.com/splitio/java-client) [Docs](https://help.split.io/hc/en-us/articles/360020405151-Java-SDK) * JavaScript [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK) * JavaScript for Browser [Github](https://github.com/splitio/javascript-browser-client) [Docs](https://help.split.io/hc/en-us/articles/360058730852-Browser-SDK) -* Node [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK) +* Node.js [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK) * PHP [Github](https://github.com/splitio/php-client) [Docs](https://help.split.io/hc/en-us/articles/360020350372-PHP-SDK) * PHP thin-client [Github](https://github.com/splitio/php-thin-client) [Docs](https://help.split.io/hc/en-us/articles/18305128673933-PHP-Thin-Client-SDK) * Python [Github](https://github.com/splitio/python-client) [Docs](https://help.split.io/hc/en-us/articles/360020359652-Python-SDK) diff --git a/webpack.common.js b/webpack.common.js index dec2458..a49136d 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -30,7 +30,7 @@ module.exports = { ], }, - node: false, // Not include Node polyfills, https://webpack.js.org/configuration/node + node: false, // Not include Node.js polyfills, https://webpack.js.org/configuration/node target: ['web', 'es5'], // target 'es5', since 'es2015' is the default in Webpack 5 externals: {