Skip to content

Commit

Permalink
Merge pull request #3 from CarsonF/feature/hooks
Browse files Browse the repository at this point in the history
Including Hooks support  🎉
  • Loading branch information
samuelcastro authored Aug 22, 2019
2 parents 6580ad7 + 89ca96f commit f48c23e
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
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;

0 comments on commit f48c23e

Please sign in to comment.