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
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,27 @@ Split allows you to [implement a custom impression listener](https://help.split.

## Usage

Now assuming you have a split named: `feature1` you can do something like:
Now assuming you have a split named `feature1` you can do something like:

```jsx
<Split name={'feature1'}>
### Hook

```tsx
const [feature1, config] = useSplit('feature1');
if (feature1 === 'on') {
return <Feature1 />;
}
```

Optional [attributes](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax)
can also be passed in:
```tsx
const [feature1, config] = useSplit('feature1', { paying_customer: true });
```

### Component

```tsx
<Split name="feature1">
{(value: TreatmentWithConfig) =>
value.treatment === 'on' ? this.renderComponent() : null
}
Expand All @@ -90,7 +107,7 @@ Now assuming you have a split named: `feature1` you can do something like:

You can optionally pass a list of splits:

```jsx
```tsx
<Split name={['feature1', 'feature2']}>
{(values: TreatmentsWithConfig) => {
console.log(values);
Expand All @@ -103,6 +120,17 @@ You can optionally pass a list of splits:
</Split>
```

### Tracking

We have a `useTrack` hook which returns the a function with the same signature as
[`client.track`](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#track).
```tsx
const track = useTrack();
function handleClick() {
const queued = track('user', 'click', 'the_button', { foo: 'bar' });
}
```

## Contributing

### Fork and Clone the Project
Expand Down
31 changes: 14 additions & 17 deletions src/Split.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useContext } from 'react';
import { SplitContext } from './SplitProvider';
import { ISplitContextValues, ISplitProps } from './types';
import { ISplitProps } from './types';

/**
* Component that will receive a split prop, connect on SplitContext and return treatment when SDK is ready.
Expand All @@ -12,20 +12,17 @@ import { ISplitContextValues, ISplitProps } from './types';
* {(value: TreatmentWithConfig) => value.treatment === 'on' ? this.renderComponent() : null}
* </Split>
*/
const Split: React.SFC<ISplitProps> = ({ name, children }) => (
<SplitContext.Consumer>
{({ client, isReady, lastUpdate }: ISplitContextValues) =>
children(
client && isReady
? name instanceof Array
? client.getTreatmentsWithConfig(name as string[])
: client.getTreatmentWithConfig(name as string)
: null,
client,
lastUpdate,
)
}
</SplitContext.Consumer>
);
const Split = ({ name, children }: ISplitProps) => {
const { client, isReady, lastUpdate } = useContext(SplitContext);
return children(
client && isReady
? name instanceof Array
? client.getTreatmentsWithConfig(name as string[])
: client.getTreatmentWithConfig(name as string)
: null,
client,
lastUpdate,
);
};

export default Split;
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default as Split } from './Split';
export { default as SplitProvider, SplitContext } from './SplitProvider';
export * from './useSplit';
export * from './useTrack';
33 changes: 33 additions & 0 deletions src/useSplit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Attributes,
TreatmentWithConfig,
} from '@splitsoftware/splitio/types/splitio';
import { useContext, useEffect, useState } from 'react';
import { SplitContext } from './SplitProvider';

/**
* Returns a treatment and it's config.
* @param {string} splitName - The string that represents the split we want to get the treatment.
* @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key.
* @returns {[string, string | null]} Tuple with treatment first and config second.
*/
export const useSplit = (
splitName: string,
attributes?: Attributes,
): [string, string | null] => {
const { client, isReady, lastUpdate } = useContext(SplitContext);
const [{ treatment, config }, setTreatment] = useState(defaultTreatment);
useEffect(() => {
const next =
client && isReady
? client.getTreatmentWithConfig(splitName, attributes)
: defaultTreatment;
setTreatment(next);
}, [client, isReady, lastUpdate]);
return [treatment, config];
};

const defaultTreatment: TreatmentWithConfig = {
config: null,
treatment: 'control', // SplitIO's default value
};
10 changes: 10 additions & 0 deletions src/useTrack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { IClient } from '@splitsoftware/splitio/types/splitio';
import { useContext } from 'react';
import { SplitContext } from './SplitProvider';

export const useTrack: () => IClient['track'] = () => {
const { client, isReady } = useContext(SplitContext);
return client && isReady ? client.track : defaultTrack;
};

const defaultTrack = () => false;