diff --git a/CHANGES.txt b/CHANGES.txt index fa3e393..be96343 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,7 +1,10 @@ -1.14.0 (October XX, 2024) +2.0.0 (October XX, 2024) - Added support for targeting rules based on large segments for browsers. - Updated @splitsoftware/splitio package to version 10.29.0 that includes minor updates, and updated some transitive dependencies for vulnerability fixes. - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. + - BREAKING CHANGES: + - Removed deprecated modules: `SplitFactory` component, `useClient`, `useTreatments` and `useManager` hooks, and `withSplitFactory`, `withSplitClient` and `withSplitTreatments` high-order components. Refer to ./MIGRATION-GUIDE.md for instructions on how to migrate to the new alternatives. + - Renamed TypeScript interfaces `ISplitFactoryProps` to `ISplitFactoryProviderProps`, and `ISplitFactoryChildProps` to `ISplitFactoryProviderChildProps`. 1.13.0 (September 6, 2024) - Updated @splitsoftware/splitio package to version 10.28.0 that includes minor updates: diff --git a/src/SplitFactory.tsx b/src/SplitFactory.tsx deleted file mode 100644 index 1636100..0000000 --- a/src/SplitFactory.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; - -import { SplitComponent } from './SplitClient'; -import { ISplitFactoryProps } from './types'; -import { WARN_SF_CONFIG_AND_FACTORY, ERROR_SF_NO_CONFIG_AND_FACTORY } from './constants'; -import { getSplitFactory, destroySplitFactory, IFactoryWithClients, getSplitClient } from './utils'; -import { DEFAULT_UPDATE_OPTIONS } from './useSplitClient'; - -/** - * SplitFactory will initialize the Split SDK and its main client, listen for its events in order to update the Split Context, - * and automatically shutdown and release resources when it is unmounted. SplitFactory must wrap other components and functions - * from this library, since they access the Split Context and its properties (factory, client, isReady, etc). - * - * The underlying SDK factory and client is set on the constructor, and cannot be changed during the component lifecycle, - * even if the component is updated with a different config or factory prop. - * - * @deprecated `SplitFactory` will be removed in a future major release. We recommend replacing it with the new `SplitFactoryProvider` component. - * - * `SplitFactoryProvider` is a revised version of `SplitFactory` that properly handles SDK side effects (i.e., factory creation and destruction) within the React component lifecycle, - * resolving memory leak issues in React development mode, strict mode and server-side rendering, and also ensuring that the SDK is updated if `config` or `factory` props change. - * - * Notable changes to consider when migrating: - * - `SplitFactoryProvider` utilizes the React Hooks API, requiring React 16.8.0 or later, while `SplitFactory` is compatible with React 16.3.0 or later. - * - When using the `config` prop with `SplitFactoryProvider`, the `factory` and `client` properties in `SplitContext` and the `manager` property in `useSplitManager` results - * are `null` in the first render, until the context is updated when some event is emitted on the SDK main client (ready, ready from cache, timeout, or update, depending on - * the configuration of the `updateOn` props of the component). This differs from the previous behavior where `factory`, `client`, and `manager` were immediately available. - * - Updating the `config` prop in `SplitFactoryProvider` reinitializes the SDK with the new configuration, while `SplitFactory` does not reinitialize the SDK. You should pass a - * reference to the configuration object (e.g., via a global variable, `useState`, or `useMemo`) rather than a new instance on each render, to avoid unnecessary reinitializations. - * - Updating the `factory` prop in `SplitFactoryProvider` replaces the current SDK instance, unlike `SplitFactory` where it is ignored. - * - * @see {@link https://help.split.io/hc/en-us/articles/360038825091-React-SDK#2-instantiate-the-sdk-and-create-a-new-split-client} - */ -export class SplitFactory extends React.Component { - - static defaultProps: ISplitFactoryProps = { - children: null, - ...DEFAULT_UPDATE_OPTIONS, - }; - - readonly state: Readonly<{ factory: SplitIO.IBrowserSDK | null, client: SplitIO.IBrowserClient | null }>; - readonly isFactoryExternal: boolean; - - constructor(props: ISplitFactoryProps) { - super(props); - - // Log warning and error - const { factory: propFactory, config } = props; - if (!config && !propFactory) { - console.error(ERROR_SF_NO_CONFIG_AND_FACTORY); - } - if (config && propFactory) { - console.log(WARN_SF_CONFIG_AND_FACTORY); - } - - // Instantiate factory - let factory = null; - if (propFactory) { - factory = propFactory; - } else { - if (config) { - // We use an idempotent variant of the Split factory builder (i.e., given the same config, it returns the same already - // created instance), since React component constructors is part of render-phase and can be invoked multiple times. - factory = getSplitFactory(config); - } - } - this.isFactoryExternal = propFactory ? true : false; - - // Instantiate main client. Attributes are set on `SplitComponent.getDerivedStateFromProps` - const client = factory ? getSplitClient(factory) : null; - - this.state = { - client, - factory, - }; - } - - componentWillUnmount() { - // only destroy the client if the factory was created internally. Otherwise, the shutdown must be handled by the user - if (!this.isFactoryExternal && this.state.factory) { - destroySplitFactory(this.state.factory as IFactoryWithClients); - } - } - - render() { - const { factory, client } = this.state; - - return ( - - ); - } -} diff --git a/src/SplitFactoryProvider.tsx b/src/SplitFactoryProvider.tsx index 0b6e8da..9b7e140 100644 --- a/src/SplitFactoryProvider.tsx +++ b/src/SplitFactoryProvider.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { SplitComponent } from './SplitClient'; -import { ISplitFactoryProps } from './types'; +import { ISplitFactoryProviderProps } from './types'; import { WARN_SF_CONFIG_AND_FACTORY } from './constants'; import { getSplitFactory, destroySplitFactory, IFactoryWithClients, getSplitClient, getStatus } from './utils'; import { DEFAULT_UPDATE_OPTIONS } from './useSplitClient'; @@ -16,7 +16,7 @@ import { DEFAULT_UPDATE_OPTIONS } from './useSplitClient'; * * @see {@link https://help.split.io/hc/en-us/articles/360038825091-React-SDK#2-instantiate-the-sdk-and-create-a-new-split-client} */ -export function SplitFactoryProvider(props: ISplitFactoryProps) { +export function SplitFactoryProvider(props: ISplitFactoryProviderProps) { let { config, factory: propFactory, updateOnSdkReady, updateOnSdkReadyFromCache, updateOnSdkTimedout, updateOnSdkUpdate diff --git a/src/__tests__/SplitFactory.test.tsx b/src/__tests__/SplitFactory.test.tsx deleted file mode 100644 index 07e649d..0000000 --- a/src/__tests__/SplitFactory.test.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import React from 'react'; -import { render, act } from '@testing-library/react'; - -/** Mocks */ -import { mockSdk, Event } from './testUtils/mockSplitSdk'; -jest.mock('@splitsoftware/splitio/client', () => { - return { SplitFactory: mockSdk() }; -}); -import { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client'; -import { sdkBrowser } from './testUtils/sdkConfigs'; -const logSpy = jest.spyOn(console, 'log'); - -/** Test target */ -import { ISplitFactoryChildProps } from '../types'; -import { SplitFactory } from '../SplitFactory'; -import { SplitClient } from '../SplitClient'; -import { SplitContext } from '../SplitContext'; -import { __factories, IClientWithContext } from '../utils'; -import { WARN_SF_CONFIG_AND_FACTORY, ERROR_SF_NO_CONFIG_AND_FACTORY } from '../constants'; - -describe('SplitFactory', () => { - - test('passes no-ready props to the child if initialized with a config.', () => { - render( - - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { - expect(factory).toBeInstanceOf(Object); - expect(isReady).toBe(false); - expect(isReadyFromCache).toBe(false); - expect(hasTimedout).toBe(false); - expect(isTimedout).toBe(false); - expect(isDestroyed).toBe(false); - expect(lastUpdate).toBe(0); - expect((factory as SplitIO.IBrowserSDK).settings.version).toContain('react-'); - return null; - }} - - ); - }); - - test('passes ready props to the child if initialized with a ready factory.', async () => { - const outerFactory = SplitSdk(sdkBrowser); - (outerFactory as any).client().__emitter__.emit(Event.SDK_READY_FROM_CACHE); - (outerFactory as any).client().__emitter__.emit(Event.SDK_READY); - (outerFactory.manager().names as jest.Mock).mockReturnValue(['split1']); - await outerFactory.client().ready(); - - render( - - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { - expect(factory).toBe(outerFactory); - expect(isReady).toBe(true); - expect(isReadyFromCache).toBe(true); - expect(hasTimedout).toBe(false); - expect(isTimedout).toBe(false); - expect(isDestroyed).toBe(false); - expect(lastUpdate).toBe((outerFactory.client() as IClientWithContext).__getStatus().lastUpdate); - expect((factory as SplitIO.IBrowserSDK).settings.version).toBe(outerFactory.settings.version); - return null; - }} - - ); - }); - - test('rerenders child on SDK_READY_TIMEDOUT, SDK_READY_FROM_CACHE, SDK_READY and SDK_UPDATE events.', async () => { - const outerFactory = SplitSdk(sdkBrowser); - let renderTimes = 0; - let previousLastUpdate = -1; - - render( - - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { - const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; - switch (renderTimes) { - case 0: // No ready - expect(statusProps).toStrictEqual([false, false, false, false]); - break; - case 1: // Timedout - expect(statusProps).toStrictEqual([false, false, true, true]); - break; - case 2: // Ready from cache - expect(statusProps).toStrictEqual([false, true, true, true]); - break; - case 3: // Ready - expect(statusProps).toStrictEqual([true, true, true, false]); - break; - case 4: // Updated - expect(statusProps).toStrictEqual([true, true, true, false]); - break; - default: - fail('Child must not be rerendered'); - } - expect(factory).toBe(outerFactory); - expect(lastUpdate).toBeGreaterThan(previousLastUpdate); - renderTimes++; - previousLastUpdate = lastUpdate; - return null; - }} - - ); - - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY_TIMED_OUT)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY_FROM_CACHE)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_UPDATE)); - - expect(renderTimes).toBe(5); - }); - - test('rerenders child on SDK_READY_TIMED_OUT and SDK_UPDATE events, but not on SDK_READY.', async () => { - const outerFactory = SplitSdk(sdkBrowser); - let renderTimes = 0; - let previousLastUpdate = -1; - - render( - - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { - const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; - switch (renderTimes) { - case 0: // No ready - expect(statusProps).toStrictEqual([false, false, false, false]); - break; - case 1: // Timedout - expect(statusProps).toStrictEqual([false, false, true, true]); - break; - case 2: // Updated. Although `updateOnSdkReady` is false, status props must reflect the current status of the client. - expect(statusProps).toStrictEqual([true, false, true, false]); - break; - default: - fail('Child must not be rerendered'); - } - expect(factory).toBe(outerFactory); - expect(lastUpdate).toBeGreaterThan(previousLastUpdate); - renderTimes++; - previousLastUpdate = lastUpdate; - return null; - }} - - ); - - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY_TIMED_OUT)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_UPDATE)); - - expect(renderTimes).toBe(3); - }); - - test('rerenders child only on SDK_READY and SDK_READY_FROM_CACHE event, as default behaviour.', async () => { - const outerFactory = SplitSdk(sdkBrowser); - let renderTimes = 0; - let previousLastUpdate = -1; - - render( - - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { - const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; - switch (renderTimes) { - case 0: // No ready - expect(statusProps).toStrictEqual([false, false, false, false]); - break; - case 1: // Ready - expect(statusProps).toStrictEqual([true, false, true, false]); // not rerendering on SDK_TIMEOUT, but hasTimedout reflects the current state - break; - default: - fail('Child must not be rerendered'); - } - expect(factory).toBe(outerFactory); - expect(lastUpdate).toBeGreaterThan(previousLastUpdate); - renderTimes++; - previousLastUpdate = lastUpdate; - return null; - }} - - ); - - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY_TIMED_OUT)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_READY)); - act(() => (outerFactory as any).client().__emitter__.emit(Event.SDK_UPDATE)); - expect(renderTimes).toBe(2); - }); - - test('renders a passed JSX.Element with a new SplitContext value.', (done) => { - const Component = () => { - return ( - - {(value) => { - expect(value.factory).toBeInstanceOf(Object); - expect(value.client).toBe(value.factory?.client()); - expect(value.isReady).toBe(false); - expect(value.isTimedout).toBe(false); - expect(value.lastUpdate).toBe(0); - done(); - return null; - }} - - ); - }; - - render( - - - - ); - }); - - test('logs warning if both a config and factory are passed as props.', () => { - const outerFactory = SplitSdk(sdkBrowser); - - render( - - {({ factory }) => { - expect(factory).toBe(outerFactory); - return null; - }} - - ); - - expect(logSpy).toBeCalledWith(WARN_SF_CONFIG_AND_FACTORY); - logSpy.mockRestore(); - }); - - test('logs error and passes null factory if rendered without a Split config and factory.', () => { - const errorSpy = jest.spyOn(console, 'error'); - render( - - {({ factory }) => { - expect(factory).toBe(null); - return null; - }} - - ); - expect(errorSpy).toBeCalledWith(ERROR_SF_NO_CONFIG_AND_FACTORY); - }); - - test('cleans up on unmount.', () => { - let destroyMainClientSpy; - let destroySharedClientSpy; - const wrapper = render( - - {({ factory }) => { - expect(__factories.size).toBe(1); - destroyMainClientSpy = jest.spyOn((factory as SplitIO.IBrowserSDK).client(), 'destroy'); - return ( - - {({ client }) => { - destroySharedClientSpy = jest.spyOn(client as SplitIO.IClient, 'destroy'); - return null; - }} - - ); - }} - - ); - wrapper.unmount(); - // the factory created by the component is removed from `factories` cache and its clients are destroyed - expect(__factories.size).toBe(0); - expect(destroyMainClientSpy).toBeCalledTimes(1); - expect(destroySharedClientSpy).toBeCalledTimes(1); - }); - - test('doesn\'t clean up on unmount if the factory is provided as a prop.', () => { - let destroyMainClientSpy; - let destroySharedClientSpy; - const outerFactory = SplitSdk(sdkBrowser); - const wrapper = render( - - {({ factory }) => { - // if factory is provided as a prop, `factories` cache is not modified - expect(__factories.size).toBe(0); - destroyMainClientSpy = jest.spyOn((factory as SplitIO.IBrowserSDK).client(), 'destroy'); - return ( - - {({ client }) => { - destroySharedClientSpy = jest.spyOn(client as SplitIO.IClient, 'destroy'); - return null; - }} - - ); - }} - - ); - wrapper.unmount(); - expect(destroyMainClientSpy).not.toBeCalled(); - expect(destroySharedClientSpy).not.toBeCalled(); - }); - -}); diff --git a/src/__tests__/SplitFactoryProvider.test.tsx b/src/__tests__/SplitFactoryProvider.test.tsx index 61cd932..0695676 100644 --- a/src/__tests__/SplitFactoryProvider.test.tsx +++ b/src/__tests__/SplitFactoryProvider.test.tsx @@ -11,7 +11,7 @@ import { sdkBrowser } from './testUtils/sdkConfigs'; const logSpy = jest.spyOn(console, 'log'); /** Test target */ -import { ISplitFactoryChildProps } from '../types'; +import { ISplitFactoryProviderChildProps } from '../types'; import { SplitFactoryProvider } from '../SplitFactoryProvider'; import { SplitClient } from '../SplitClient'; import { INITIAL_CONTEXT, SplitContext } from '../SplitContext'; @@ -23,7 +23,7 @@ describe('SplitFactoryProvider', () => { test('passes no-ready props to the child if initialized with a config.', () => { render( - {({ factory, client, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, client, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryProviderChildProps) => { expect(factory).toBe(null); expect(client).toBe(null); expect(isReady).toBe(false); @@ -47,7 +47,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryProviderChildProps) => { expect(factory).toBe(outerFactory); expect(isReady).toBe(true); expect(isReadyFromCache).toBe(true); @@ -68,7 +68,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -114,7 +114,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -158,7 +158,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -197,7 +197,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -234,7 +234,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -269,7 +269,7 @@ describe('SplitFactoryProvider', () => { render( - {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryChildProps) => { + {({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, lastUpdate }: ISplitFactoryProviderChildProps) => { const statusProps = [isReady, isReadyFromCache, hasTimedout, isTimedout]; switch (renderTimes) { case 0: // No ready @@ -338,7 +338,7 @@ describe('SplitFactoryProvider', () => { const clientDestroySpies: jest.SpyInstance[] = []; const outerFactory = SplitSdk(sdkBrowser); - const Component = ({ factory, isReady, hasTimedout }: ISplitFactoryChildProps) => { + const Component = ({ factory, isReady, hasTimedout }: ISplitFactoryProviderChildProps) => { renderTimes++; switch (renderTimes) { diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index b0b3538..8005083 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -2,17 +2,10 @@ import { SplitContext as ExportedSplitContext, SplitSdk as ExportedSplitSdk, - SplitFactory as ExportedSplitFactory, SplitFactoryProvider as ExportedSplitFactoryProvider, SplitClient as ExportedSplitClient, SplitTreatments as ExportedSplitTreatments, - withSplitFactory as exportedWithSplitFactory, - withSplitClient as exportedWithSplitClient, - withSplitTreatments as exportedWithSplitTreatments, - useClient as exportedUseClient, - useManager as exportedUseManager, useTrack as exportedUseTrack, - useTreatments as exportedUseTreatments, useSplitClient as exportedUseSplitClient, useSplitTreatments as exportedUseSplitTreatments, useSplitManager as exportedUseSplitManager, @@ -21,8 +14,8 @@ import { ISplitClientChildProps, ISplitClientProps, ISplitContextValues, - ISplitFactoryChildProps, - ISplitFactoryProps, + ISplitFactoryProviderChildProps, + ISplitFactoryProviderProps, ISplitStatus, ISplitTreatmentsChildProps, ISplitTreatmentsProps, @@ -32,17 +25,10 @@ import { } from '../index'; import { SplitContext } from '../SplitContext'; import { SplitFactory as SplitioEntrypoint } from '@splitsoftware/splitio/client'; -import { SplitFactory } from '../SplitFactory'; import { SplitFactoryProvider } from '../SplitFactoryProvider'; import { SplitClient } from '../SplitClient'; import { SplitTreatments } from '../SplitTreatments'; -import { withSplitFactory } from '../withSplitFactory'; -import { withSplitClient } from '../withSplitClient'; -import { withSplitTreatments } from '../withSplitTreatments'; -import { useClient } from '../useClient'; -import { useManager } from '../useManager'; import { useTrack } from '../useTrack'; -import { useTreatments } from '../useTreatments'; import { useSplitClient } from '../useSplitClient'; import { useSplitTreatments } from '../useSplitTreatments'; import { useSplitManager } from '../useSplitManager'; @@ -50,23 +36,13 @@ import { useSplitManager } from '../useSplitManager'; describe('index', () => { it('should export components', () => { - expect(ExportedSplitFactory).toBe(SplitFactory); expect(ExportedSplitFactoryProvider).toBe(SplitFactoryProvider); expect(ExportedSplitClient).toBe(SplitClient); expect(ExportedSplitTreatments).toBe(SplitTreatments); }); - it('should export HOCs', () => { - expect(exportedWithSplitFactory).toBe(withSplitFactory); - expect(exportedWithSplitClient).toBe(withSplitClient); - expect(exportedWithSplitTreatments).toBe(withSplitTreatments); - }); - it('should export hooks', () => { - expect(exportedUseClient).toBe(useClient); - expect(exportedUseManager).toBe(useManager); expect(exportedUseTrack).toBe(useTrack); - expect(exportedUseTreatments).toBe(useTreatments); expect(exportedUseSplitClient).toBe(useSplitClient); expect(exportedUseSplitTreatments).toBe(useSplitTreatments); expect(exportedUseSplitManager).toBe(useSplitManager); diff --git a/src/__tests__/useClient.test.tsx b/src/__tests__/useClient.test.tsx deleted file mode 100644 index 544e843..0000000 --- a/src/__tests__/useClient.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/** Mocks */ -const useSplitClientMock = jest.fn(); -jest.mock('../useSplitClient', () => ({ - useSplitClient: useSplitClientMock -})); - -/** Test target */ -import { useClient } from '../useClient'; - -describe('useClient', () => { - - test('calls useSplitClient with the correct arguments and returns the client.', () => { - const attributes = { someAttribute: 'someValue' }; - const client = 'client'; - useSplitClientMock.mockReturnValue({ client, isReady: false }); - - expect(useClient('someKey', 'someTrafficType', attributes)).toBe(client); - - expect(useSplitClientMock).toHaveBeenCalledTimes(1); - expect(useSplitClientMock).toHaveBeenCalledWith({ splitKey: 'someKey', trafficType: 'someTrafficType', attributes }); - }); - -}); diff --git a/src/__tests__/useManager.test.tsx b/src/__tests__/useManager.test.tsx deleted file mode 100644 index ba4c36c..0000000 --- a/src/__tests__/useManager.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** Mocks */ -const useSplitManagerMock = jest.fn(); -jest.mock('../useSplitManager', () => ({ - useSplitManager: useSplitManagerMock -})); - -/** Test target */ -import { useManager } from '../useManager'; - -describe('useManager', () => { - - test('calls useSplitManager with the correct arguments and returns the manager.', () => { - const manager = 'manager'; - useSplitManagerMock.mockReturnValue({ manager, isReady: false }); - - expect(useManager()).toBe(manager); - - expect(useSplitManagerMock).toHaveBeenCalledTimes(1); - }); - -}); diff --git a/src/__tests__/useTreatments.test.tsx b/src/__tests__/useTreatments.test.tsx deleted file mode 100644 index b375d05..0000000 --- a/src/__tests__/useTreatments.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** Mocks */ -const useSplitTreatmentsMock = jest.fn(); -jest.mock('../useSplitTreatments', () => ({ - useSplitTreatments: useSplitTreatmentsMock -})); - -/** Test target */ -import { useTreatments } from '../useTreatments'; - -describe('useTreatments', () => { - - test('calls useSplitTreatments with the correct arguments and returns the treatments.', () => { - const names = ['someFeature']; - const attributes = { someAttribute: 'someValue' }; - const treatments = { someFeature: { treatment: 'on', config: null } }; - useSplitTreatmentsMock.mockReturnValue({ treatments, isReady: false }); - - expect(useTreatments(names, attributes, 'someKey')).toBe(treatments); - - expect(useSplitTreatmentsMock).toHaveBeenCalledTimes(1); - expect(useSplitTreatmentsMock).toHaveBeenCalledWith({ names, attributes, splitKey: 'someKey' }); - }); - -}); diff --git a/src/__tests__/withSplitClient.test.tsx b/src/__tests__/withSplitClient.test.tsx deleted file mode 100644 index 85ba3ad..0000000 --- a/src/__tests__/withSplitClient.test.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; - -/** Mocks */ -import { mockSdk, Event } from './testUtils/mockSplitSdk'; -jest.mock('@splitsoftware/splitio/client', () => { - return { SplitFactory: mockSdk() }; -}); -import { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client'; -import { sdkBrowser } from './testUtils/sdkConfigs'; -import * as SplitClient from '../SplitClient'; -const SplitClientSpy = jest.spyOn(SplitClient, 'SplitClient'); -import { testAttributesBinding, TestComponentProps } from './testUtils/utils'; - -/** Test target */ -import { withSplitFactory } from '../withSplitFactory'; -import { withSplitClient } from '../withSplitClient'; - -describe('SplitClient', () => { - - test('passes no-ready props to the child if client is not ready.', () => { - const Component = withSplitFactory(sdkBrowser)( - withSplitClient('user1')( - ({ client, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }) => { - expect(client).not.toBe(null); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]); - return null; - } - ) - ); - render(); - }); - - test('passes ready props to the child if client is ready.', (done) => { - const outerFactory = SplitSdk(sdkBrowser); - (outerFactory as any).client().__emitter__.emit(Event.SDK_READY); - (outerFactory.manager().names as jest.Mock).mockReturnValue(['split1']); - outerFactory.client().ready().then(() => { - const Component = withSplitFactory(undefined, outerFactory)( - withSplitClient('user1')( - ({ client, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }) => { - expect(client).toBe(outerFactory.client('user1')); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]); - return null; - } - ) - ); - render(); - done(); - }); - }); - - test('passes Split props and outer props to the child.', () => { - const Component = withSplitFactory(sdkBrowser)<{ outerProp1: string, outerProp2: number }>( - withSplitClient('user1')<{ outerProp1: string, outerProp2: number }>( - ({ outerProp1, outerProp2, client, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }) => { - expect(outerProp1).toBe('outerProp1'); - expect(outerProp2).toBe(2); - expect(client).not.toBe(null); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]); - return null; - } - ) - ); - render(); - }); - - test('passes Status props to SplitClient.', () => { - const updateOnSdkUpdate = true; - const updateOnSdkTimedout = false; - const updateOnSdkReady = true; - const updateOnSdkReadyFromCache = false; - const Component = withSplitClient('user1')<{ outerProp1: string, outerProp2: number }>( - () => null, updateOnSdkUpdate, updateOnSdkTimedout, updateOnSdkReady, updateOnSdkReadyFromCache - ); - render(); - - expect(SplitClientSpy).toHaveBeenLastCalledWith( - expect.objectContaining({ - updateOnSdkUpdate, - updateOnSdkTimedout, - updateOnSdkReady, - updateOnSdkReadyFromCache, - }), - expect.anything() - ); - }); - - test('attributes binding test with utility', (done) => { - - function Component({ attributesFactory, attributesClient, splitKey, testSwitch, factory }: TestComponentProps) { - const FactoryComponent = withSplitFactory(undefined, factory, attributesFactory)<{ attributesClient: SplitIO.Attributes, splitKey: any }>( - ({ attributesClient, splitKey }) => { - const ClientComponent = withSplitClient(splitKey, 'user', attributesClient)( - () => { - testSwitch(done, splitKey); - return null; - }) - return ; - } - ) - return - } - - testAttributesBinding(Component); - }); - -}); diff --git a/src/__tests__/withSplitFactory.test.tsx b/src/__tests__/withSplitFactory.test.tsx deleted file mode 100644 index 6df93f6..0000000 --- a/src/__tests__/withSplitFactory.test.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; - -/** Mocks */ -import { mockSdk, Event } from './testUtils/mockSplitSdk'; -jest.mock('@splitsoftware/splitio/client', () => { - return { SplitFactory: mockSdk() }; -}); -import { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client'; -import { sdkBrowser } from './testUtils/sdkConfigs'; -import { SplitFactory } from '../SplitFactory'; -jest.mock('../SplitFactory'); - -/** Test target */ -import { ISplitFactoryChildProps } from '../types'; -import { withSplitFactory } from '../withSplitFactory'; - -describe('withSplitFactory', () => { - - test('passes no-ready props to the child if initialized with a no ready factory (e.g., using config object).', () => { - const Component = withSplitFactory(sdkBrowser)( - ({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { - expect(factory).toBeInstanceOf(Object); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]); - return null; - } - ); - render(); - }); - - test('passes ready props to the child if initialized with a ready factory.', (done) => { - const outerFactory = SplitSdk(sdkBrowser); - (outerFactory as any).client().__emitter__.emit(Event.SDK_READY); - (outerFactory.manager().names as jest.Mock).mockReturnValue(['split1']); - outerFactory.client().ready().then(() => { - const Component = withSplitFactory(undefined, outerFactory)( - ({ factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }: ISplitFactoryChildProps) => { - expect(factory).toBe(outerFactory); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([true, false, false, false, false, 0]); - return null; - } - ); - render(); - done(); - }); - }); - - test('passes Split props and outer props to the child.', () => { - const Component = withSplitFactory(sdkBrowser)<{ outerProp1: string, outerProp2: number }>( - ({ outerProp1, outerProp2, factory, isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate }) => { - expect(outerProp1).toBe('outerProp1'); - expect(outerProp2).toBe(2); - expect(factory).toBeInstanceOf(Object); - expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]); - return null; - } - ); - render(); - }); - - test('passes Status props to SplitFactory.', () => { - const updateOnSdkUpdate = true; - const updateOnSdkTimedout = false; - const updateOnSdkReady = true; - const updateOnSdkReadyFromCache = false; - const Component = withSplitFactory(sdkBrowser)<{ outerProp1: string, outerProp2: number }>( - () => null, updateOnSdkUpdate, updateOnSdkTimedout, updateOnSdkReady, updateOnSdkReadyFromCache - ); - - render(); - - expect(SplitFactory).toHaveBeenLastCalledWith( - expect.objectContaining({ - updateOnSdkUpdate, - updateOnSdkTimedout, - updateOnSdkReady, - updateOnSdkReadyFromCache - }), - expect.anything(), - ); - }); - -}); diff --git a/src/__tests__/withSplitTreatments.test.tsx b/src/__tests__/withSplitTreatments.test.tsx deleted file mode 100644 index f5d523b..0000000 --- a/src/__tests__/withSplitTreatments.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; - -/** Mocks */ -import { mockSdk } from './testUtils/mockSplitSdk'; -jest.mock('@splitsoftware/splitio/client', () => { - return { SplitFactory: mockSdk() }; -}); -import { sdkBrowser } from './testUtils/sdkConfigs'; - -/** Test target */ -import { withSplitFactory } from '../withSplitFactory'; -import { withSplitClient } from '../withSplitClient'; -import { withSplitTreatments } from '../withSplitTreatments'; -import { getControlTreatmentsWithConfig } from '../utils'; - -describe('withSplitTreatments', () => { - - it(`passes Split props and outer props to the child. - In this test, the value of "props.treatments" is obtained by the function "getControlTreatmentsWithConfig", - and not "client.getTreatmentsWithConfig" since the client is not ready.`, () => { - const featureFlagNames = ['split1', 'split2']; - - const Component = withSplitFactory(sdkBrowser)<{ outerProp1: string, outerProp2: number }>( - ({ outerProp1, outerProp2, factory }) => { - const SubComponent = withSplitClient('user1')<{ outerProp1: string, outerProp2: number }>( - withSplitTreatments(featureFlagNames)( - (props) => { - const clientMock = factory!.client('user1'); - expect((clientMock.getTreatmentsWithConfig as jest.Mock).mock.calls.length).toBe(0); - - expect(props).toStrictEqual({ - factory: factory, client: clientMock, - outerProp1: 'outerProp1', outerProp2: 2, - treatments: getControlTreatmentsWithConfig(featureFlagNames), - isReady: false, - isReadyFromCache: false, - hasTimedout: false, - isTimedout: false, - isDestroyed: false, - lastUpdate: 0 - }); - - return null; - } - ) - ); - return ; - }); - - render(); - }); - -}); diff --git a/src/constants.ts b/src/constants.ts index c29d802..2bd1b08 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,9 +16,6 @@ export const CONTROL_WITH_CONFIG: SplitIO.TreatmentWithConfig = { // Warning and error messages export const WARN_SF_CONFIG_AND_FACTORY: string = '[WARN] Both a config and factory props were provided to SplitFactoryProvider. Config prop will be ignored.'; -// @TODO remove with SplitFactory component in next major version. SplitFactoryProvider can accept no props and eventually only an initialState -export const ERROR_SF_NO_CONFIG_AND_FACTORY: string = '[ERROR] SplitFactory must receive either a Split config or a Split factory as props.'; - export const EXCEPTION_NO_REACT_OR_CREATECONTEXT: string = 'React library is not available or its version is not supported. Check that it is properly installed or imported. Split SDK requires version 16.3.0+ of React.'; export const WARN_NAMES_AND_FLAGSETS: string = '[WARN] Both names and flagSets properties were provided. flagSets will be ignored.'; diff --git a/src/index.ts b/src/index.ts index 10a5161..cb76510 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,22 +1,13 @@ // Split SDK factory (Renamed to avoid name conflict with SplitFactory component) export { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client'; -// HOC functions -export { withSplitFactory } from './withSplitFactory'; -export { withSplitClient } from './withSplitClient'; -export { withSplitTreatments } from './withSplitTreatments'; - // Components export { SplitTreatments } from './SplitTreatments'; export { SplitClient } from './SplitClient'; -export { SplitFactory } from './SplitFactory'; export { SplitFactoryProvider } from './SplitFactoryProvider'; // Hooks -export { useClient } from './useClient'; -export { useTreatments } from './useTreatments'; export { useTrack } from './useTrack'; -export { useManager } from './useManager'; export { useSplitClient } from './useSplitClient'; export { useSplitTreatments } from './useSplitTreatments'; export { useSplitManager } from './useSplitManager'; @@ -30,8 +21,8 @@ export type { ISplitClientChildProps, ISplitClientProps, ISplitContextValues, - ISplitFactoryChildProps, - ISplitFactoryProps, + ISplitFactoryProviderChildProps, + ISplitFactoryProviderProps, ISplitStatus, ISplitTreatmentsChildProps, ISplitTreatmentsProps, diff --git a/src/types.ts b/src/types.ts index c6ff17d..88d7006 100644 --- a/src/types.ts +++ b/src/types.ts @@ -100,17 +100,15 @@ export interface IUpdateProps { } /** - * SplitFactoryProvider Child Props interface. These are the props that the child component receives from the 'SplitFactoryProvider' component. + * SplitFactoryProvider Child Props interface. These are the props that the child as a function receives from the 'SplitFactoryProvider' component. */ -// @TODO rename/remove next type (breaking-change) -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ISplitFactoryChildProps extends ISplitContextValues { } +export interface ISplitFactoryProviderChildProps extends ISplitContextValues { } /** * SplitFactoryProvider Props interface. These are the props accepted by SplitFactoryProvider component, * used to instantiate a factory and client instance, update the Split context, and listen for SDK events. */ -export interface ISplitFactoryProps extends IUpdateProps { +export interface ISplitFactoryProviderProps extends IUpdateProps { /** * Config object used to instantiate a Split factory @@ -133,7 +131,7 @@ export interface ISplitFactoryProps extends IUpdateProps { /** * Children of the SplitFactoryProvider component. It can be a functional component (child as a function) or a React element. */ - children: ((props: ISplitFactoryChildProps) => ReactNode) | ReactNode; + children: ((props: ISplitFactoryProviderChildProps) => ReactNode) | ReactNode; } /** @@ -160,10 +158,8 @@ export interface IUseSplitClientOptions extends IUpdateProps { } /** - * SplitClient Child Props interface. These are the props that the child component receives from the 'SplitClient' component. + * SplitClient Child Props interface. These are the props that the child as a function receives from the 'SplitClient' component. */ -// @TODO remove next type (breaking-change) -// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ISplitClientChildProps extends ISplitContextValues { } /** diff --git a/src/useClient.ts b/src/useClient.ts deleted file mode 100644 index 7428b60..0000000 --- a/src/useClient.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useSplitClient } from './useSplitClient'; - -/** - * 'useClient' is a hook that returns a client from the Split context. - * It uses the 'useContext' hook to access the context, which is updated by - * SplitFactoryProvider and SplitClient components in the hierarchy of components. - * - * @returns A Split Client instance, or null if used outside the scope of SplitFactoryProvider or factory is not ready. - * - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#advanced-instantiate-multiple-sdk-clients} - * - * @deprecated Replace with the new `useSplitClient` hook. - */ -export function useClient(splitKey?: SplitIO.SplitKey, trafficType?: string, attributes?: SplitIO.Attributes): SplitIO.IBrowserClient | null { - return useSplitClient({ splitKey, trafficType, attributes }).client; -} diff --git a/src/useManager.ts b/src/useManager.ts deleted file mode 100644 index 094ec99..0000000 --- a/src/useManager.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useSplitManager } from './useSplitManager'; - -/** - * 'useManager' is a hook that returns the Manager instance from the Split factory. - * It uses the 'useContext' hook to access the factory at Split context, which is updated by - * the SplitFactoryProvider component. - * - * @returns A Split Manager instance, or null if used outside the scope of SplitFactoryProvider or factory is not ready. - * - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#manager} - * - * @deprecated Replace with the new `useSplitManager` hook. - */ -export function useManager(): SplitIO.IManager | null { - return useSplitManager().manager; -} diff --git a/src/useTreatments.ts b/src/useTreatments.ts deleted file mode 100644 index bd673fa..0000000 --- a/src/useTreatments.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useSplitTreatments } from './useSplitTreatments'; - -/** - * 'useTreatments' is a hook that returns an object of feature flag evaluations (i.e., treatments). - * It uses the 'useContext' hook to access the client from the Split context, - * and invokes the 'getTreatmentsWithConfig' method. - * - * @returns A TreatmentsWithConfig instance, that might contain control treatments if the client is not available or ready, or if feature flag names do not exist. - * - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#get-treatments-with-configurations} - * - * @deprecated Replace with the new `useSplitTreatments` hook. - */ -export function useTreatments(featureFlagNames: string[], attributes?: SplitIO.Attributes, splitKey?: SplitIO.SplitKey): SplitIO.TreatmentsWithConfig { - return useSplitTreatments({ names: featureFlagNames, attributes, splitKey }).treatments; -} diff --git a/src/withSplitClient.tsx b/src/withSplitClient.tsx deleted file mode 100644 index f6689f4..0000000 --- a/src/withSplitClient.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import { ISplitClientChildProps } from './types'; -import { SplitClient } from './SplitClient'; - -/** - * High-Order Component for SplitClient. - * The wrapped component receives all the props of the container, - * along with the passed props from SplitClient (see ISplitClientChildProps). - * - * @param splitKey The customer identifier. - * @param trafficType Traffic type associated with the customer identifier. If no provided here or at the config object, it will be required on the client.track() calls. - */ -export function withSplitClient(splitKey: SplitIO.SplitKey, trafficType?: string, attributes?: SplitIO.Attributes) { - - return function withSplitClientHoc( - WrappedComponent: React.ComponentType, - updateOnSdkUpdate = false, - updateOnSdkTimedout = false, - updateOnSdkReady = true, - updateOnSdkReadyFromCache = true, - ) { - - return function wrapper(props: OuterProps) { - return ( - - {(splitProps) => { - return ( - - ); - }} - - ); - }; - }; -} diff --git a/src/withSplitFactory.tsx b/src/withSplitFactory.tsx deleted file mode 100644 index fd83a0e..0000000 --- a/src/withSplitFactory.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; -import { ISplitFactoryChildProps } from './types'; -import { SplitFactory } from './SplitFactory'; - -/** - * High-Order Component for SplitFactory. - * The wrapped component receives all the props of the container, - * along with the passed props from SplitFactory (see ISplitFactoryChildProps). - * - * @param config Config object used to instantiate a Split factory - * @param factory Split factory instance to use instead of creating a new one with the config object. - * - * @deprecated `withSplitFactory` will be removed in a future major release. We recommend replacing it with the new `SplitFactoryProvider` component. - * - * `SplitFactoryProvider` is a revised version of `SplitFactory` that properly handles SDK side effects (i.e., factory creation and destruction) within the React component lifecycle, - * resolving memory leak issues in React development mode, strict mode and server-side rendering, and also ensuring that the SDK is updated if `config` or `factory` props change. - * - * Notable changes to consider when migrating: - * - `SplitFactoryProvider` utilizes the React Hooks API, requiring React 16.8.0 or later, while `SplitFactory` is compatible with React 16.3.0 or later. - * - When using the `config` prop with `SplitFactoryProvider`, the `factory` and `client` properties in `SplitContext` and the `manager` property in `useSplitManager` results - * are `null` in the first render, until the context is updated when some event is emitted on the SDK main client (ready, ready from cache, timeout, or update, depending on - * the configuration of the `updateOn` props of the component). This differs from the previous behavior where `factory`, `client`, and `manager` were immediately available. - * - Updating the `config` prop in `SplitFactoryProvider` reinitializes the SDK with the new configuration, while `SplitFactory` does not reinitialize the SDK. You should pass a - * reference to the configuration object (e.g., via a global variable, `useState`, or `useMemo`) rather than a new instance on each render, to avoid unnecessary reinitializations. - * - Updating the `factory` prop in `SplitFactoryProvider` replaces the current SDK instance, unlike `SplitFactory` where it is ignored. - */ -export function withSplitFactory(config?: SplitIO.IBrowserSettings, factory?: SplitIO.IBrowserSDK, attributes?: SplitIO.Attributes) { - - return function withSplitFactoryHoc( - WrappedComponent: React.ComponentType, - updateOnSdkUpdate = false, - updateOnSdkTimedout = false, - updateOnSdkReady = true, - updateOnSdkReadyFromCache = true, - ) { - - return function wrapper(props: OuterProps) { - return ( - - {(splitProps) => { - return ( - - ); - }} - - ); - }; - }; -} diff --git a/src/withSplitTreatments.tsx b/src/withSplitTreatments.tsx deleted file mode 100644 index 6d0607a..0000000 --- a/src/withSplitTreatments.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { ISplitTreatmentsChildProps } from './types'; -import { SplitTreatments } from './SplitTreatments'; - -/** - * High-Order Component for SplitTreatments. - * The wrapped component receives all the props of the container, - * along with the passed props from SplitTreatments (see ISplitTreatmentsChildProps). - * - * @param names list of feature flag names - * @param attributes An object of type Attributes used to evaluate the feature flags. - */ -export function withSplitTreatments(names: string[], attributes?: SplitIO.Attributes) { - - return function withSplitTreatmentsHoc( - WrappedComponent: React.ComponentType, - ) { - - return function wrapper(props: OuterProps) { - return ( - - {(splitProps) => { - return ( - - ); - }} - - ); - }; - }; -} diff --git a/umd.ts b/umd.ts index 6beea58..57f44af 100644 --- a/umd.ts +++ b/umd.ts @@ -1,15 +1,13 @@ import { SplitSdk, - withSplitFactory, withSplitClient, withSplitTreatments, - SplitFactory, SplitFactoryProvider, SplitClient, SplitTreatments, - useClient, useSplitClient, useTreatments, useSplitTreatments, useTrack, useManager, useSplitManager, + SplitFactoryProvider, SplitClient, SplitTreatments, + useSplitClient, useSplitTreatments, useTrack, useSplitManager, SplitContext, } from './src/index'; export default { SplitSdk, - withSplitFactory, withSplitClient, withSplitTreatments, - SplitFactory, SplitFactoryProvider, SplitClient, SplitTreatments, - useClient, useSplitClient, useTreatments, useSplitTreatments, useTrack, useManager, useSplitManager, + SplitFactoryProvider, SplitClient, SplitTreatments, + useSplitClient, useSplitTreatments, useTrack, useSplitManager, SplitContext, };