Skip to content

Commit f48c23e

Browse files
authored
Merge pull request #3 from CarsonF/feature/hooks
Including Hooks support 🎉
2 parents 6580ad7 + 89ca96f commit f48c23e

5 files changed

Lines changed: 91 additions & 21 deletions

File tree

README.md

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,27 @@ Split allows you to [implement a custom impression listener](https://help.split.
7878

7979
## Usage
8080

81-
Now assuming you have a split named: `feature1` you can do something like:
81+
Now assuming you have a split named `feature1` you can do something like:
8282

83-
```jsx
84-
<Split name={'feature1'}>
83+
### Hook
84+
85+
```tsx
86+
const [feature1, config] = useSplit('feature1');
87+
if (feature1 === 'on') {
88+
return <Feature1 />;
89+
}
90+
```
91+
92+
Optional [attributes](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax)
93+
can also be passed in:
94+
```tsx
95+
const [feature1, config] = useSplit('feature1', { paying_customer: true });
96+
```
97+
98+
### Component
99+
100+
```tsx
101+
<Split name="feature1">
85102
{(value: TreatmentWithConfig) =>
86103
value.treatment === 'on' ? this.renderComponent() : null
87104
}
@@ -90,7 +107,7 @@ Now assuming you have a split named: `feature1` you can do something like:
90107

91108
You can optionally pass a list of splits:
92109

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

123+
### Tracking
124+
125+
We have a `useTrack` hook which returns the a function with the same signature as
126+
[`client.track`](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#track).
127+
```tsx
128+
const track = useTrack();
129+
function handleClick() {
130+
const queued = track('user', 'click', 'the_button', { foo: 'bar' });
131+
}
132+
```
133+
106134
## Contributing
107135

108136
### Fork and Clone the Project

src/Split.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React from 'react';
1+
import { useContext } from 'react';
22
import { SplitContext } from './SplitProvider';
3-
import { ISplitContextValues, ISplitProps } from './types';
3+
import { ISplitProps } from './types';
44

55
/**
66
* Component that will receive a split prop, connect on SplitContext and return treatment when SDK is ready.
@@ -12,20 +12,17 @@ import { ISplitContextValues, ISplitProps } from './types';
1212
* {(value: TreatmentWithConfig) => value.treatment === 'on' ? this.renderComponent() : null}
1313
* </Split>
1414
*/
15-
const Split: React.SFC<ISplitProps> = ({ name, children }) => (
16-
<SplitContext.Consumer>
17-
{({ client, isReady, lastUpdate }: ISplitContextValues) =>
18-
children(
19-
client && isReady
20-
? name instanceof Array
21-
? client.getTreatmentsWithConfig(name as string[])
22-
: client.getTreatmentWithConfig(name as string)
23-
: null,
24-
client,
25-
lastUpdate,
26-
)
27-
}
28-
</SplitContext.Consumer>
29-
);
15+
const Split = ({ name, children }: ISplitProps) => {
16+
const { client, isReady, lastUpdate } = useContext(SplitContext);
17+
return children(
18+
client && isReady
19+
? name instanceof Array
20+
? client.getTreatmentsWithConfig(name as string[])
21+
: client.getTreatmentWithConfig(name as string)
22+
: null,
23+
client,
24+
lastUpdate,
25+
);
26+
};
3027

3128
export default Split;

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export { default as Split } from './Split';
22
export { default as SplitProvider, SplitContext } from './SplitProvider';
3+
export * from './useSplit';
4+
export * from './useTrack';

src/useSplit.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {
2+
Attributes,
3+
TreatmentWithConfig,
4+
} from '@splitsoftware/splitio/types/splitio';
5+
import { useContext, useEffect, useState } from 'react';
6+
import { SplitContext } from './SplitProvider';
7+
8+
/**
9+
* Returns a treatment and it's config.
10+
* @param {string} splitName - The string that represents the split we want to get the treatment.
11+
* @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key.
12+
* @returns {[string, string | null]} Tuple with treatment first and config second.
13+
*/
14+
export const useSplit = (
15+
splitName: string,
16+
attributes?: Attributes,
17+
): [string, string | null] => {
18+
const { client, isReady, lastUpdate } = useContext(SplitContext);
19+
const [{ treatment, config }, setTreatment] = useState(defaultTreatment);
20+
useEffect(() => {
21+
const next =
22+
client && isReady
23+
? client.getTreatmentWithConfig(splitName, attributes)
24+
: defaultTreatment;
25+
setTreatment(next);
26+
}, [client, isReady, lastUpdate]);
27+
return [treatment, config];
28+
};
29+
30+
const defaultTreatment: TreatmentWithConfig = {
31+
config: null,
32+
treatment: 'control', // SplitIO's default value
33+
};

src/useTrack.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { IClient } from '@splitsoftware/splitio/types/splitio';
2+
import { useContext } from 'react';
3+
import { SplitContext } from './SplitProvider';
4+
5+
export const useTrack: () => IClient['track'] = () => {
6+
const { client, isReady } = useContext(SplitContext);
7+
return client && isReady ? client.track : defaultTrack;
8+
};
9+
10+
const defaultTrack = () => false;

0 commit comments

Comments
 (0)