react-client
react-client copied to clipboard
[Feature request] useTreatment and useTreatmentWithConfig hooks
For our team's use case, we often want to get a single split and its treatments. It seems that getTreatment and getTreatmentWithConfig from the underlying javascript-SDK are not currently available as React hooks, but I may have overlooked it in the codebase!
Here's the API I'm thinking of.
const treatment = useTreatment('my_split');
if (treatment === 'on') {
return <OnComponent />
}
return <OffComponent />
Would you be open to me submitting a PR for this? Thank you!
Hi @besh , did you check the doc page? We do have an example for the SDK using react hooks: https://help.split.io/hc/en-us/articles/360038825091-React-SDK#using-the-sdk
See below, the featureName is set to one split name, and the treatment returned is only for one split:
mport { useContext } from 'react'; import { useTreatments, SplitContext } from '@splitsoftware/splitio-react'; import MyComponentV1 from './MyComponentV1'; import MyComponentV2 from './MyComponentV2'; const featureName = 'SPLIT_NAME'; function renderContent(treatmentWithConfig, props) { const { treatment, config } = treatmentWithConfig; if (treatment === 'on') return (<MyComponentV2 config={config} {...props} />); return (<MyComponentV1 config={config} {...props} />); } /**
- This is onether way to write a toggler with a function component that uses hooks.
**/
function MyComponentToggle (props) {
// access status properties via the SplitContext
const { isReady } = useContext(SplitContext);
// evaluate splits with the
useTreatmentshook const treatments = useTreatments([featureName]); return isReady ? renderContent(treatments[featureName], props) : // Use the treatments and configs. <Spinner />; // Render a spinner if the SDK is not ready yet. You can do what you want with this boolean. ); } // As an alternative you could use our equivalent HOC export default MyComponentToggle;
@chillaq, thank you.
I did see that example. However, const treatments = useTreatments([featureName]); is at the core of that example, where you still must pass in an array of one item. The treatment is still accessed through treatments.featureName.treatment. In the example above, treatments.featureName is passed into the component as a prop and not readily available via a hook.
I want to add a useTreatment(splitName) to this SDK, which directly returns the treatment for that split. This simple hook would be more streamlined for our use cases, and it would also bring feature parity with other SDKs such as the Ruby SDK and the JavaScript SDK that offer methods to retrieve a single split treatment.
I'll have some time tomorrow to push up a PR for the team to review.
Draft PR: https://github.com/splitio/react-client/pull/70
Hi @besh ,
Thank you for your suggestion and draft PR. We will take it into account, but we cannot prioritize that work at the moment.
For your information, we have provided only one version of useTreatments hook and SplitTreatments component because that is the most general one of the 4 "getTreatment..." methods you can find in our SDKs: getTreatment, getTreatments, getTreatmentWithConfig and getTreatmentsWithConfig.
Any other "hook" variant can be simply derived from the provided one. For instance, the hook equivalent to getTreatment (the one you are requiring) can be implemented on your side with the following code:
const useTreatment = (splitName: string, attributes?: SplitIO.Attributes, key?: SplitIO.SplitKey): SplitIO.Treatment => {
return useTreatments([splitName], attributes, key)[splitName].treatment;
}
The one for getTreatmentWithConfig might be:
const useTreatmentWithConfig = (splitName: string, attributes?: SplitIO.Attributes, key?: SplitIO.SplitKey): SplitIO.TreatmentWithConfig => {
return useTreatments([splitName], attributes, key)[splitName];
}
and so on.
@EmilianoSanchez understood.
Aw. I was hoping to get these hooks into the core package to bring about feature parity with the other SDKs instead of having our own wrapping package. However, if this is not something that would benefit the Split community, then I suppose that may be our only option.
Is it work you'd like to prioritize in the future? I certainly don't mind finalizing my PR and prepping it for then.
Hi @besh
Is it work you'd like to prioritize in the future? I certainly don't mind finalizing my PR and prepping it for then.
Yes, we will prioritize it in the future, but for consistency we consider that this change should be done as a breaking change (v2.0.0), because the current useTreatments hook should be renamed to useTreatmentsWithConfig in order to add your suggested hook -useTreatment- and the remaining ones -useTreatments and useTreatmentWithConfig-.
So, we will consider your suggestion and retake your PR in the future, but there is not an ETA yet for the next major release.
@EmilianoSanchez Got it, and thank you for the response. When you're ready, I'd be happy to help in the future.
For now, we wrote a little wrapper lib. We found that most of our historical use cases of feature flags (maybe even all) were simple on/off. With that, we created a simplified hook to return a boolean to avoid string equality checking.
type UseFeatureFlagOptions = {
attributes?: SplitIO.Attributes;
key?: SplitIO.SplitKey;
variantName?: string;
};
const useFeatureFlag = (flagName: string, options?: UseFeatureFlagOptions): boolean => {
const { variantName, attributes, key }: UseFeatureFlagOptions = {
variantName: 'on',
...options,
};
const flag = useTreatments([flagName], attributes, key)[flagName];
return flag && flag.treatment === variantName;
};
In most cases, we would just do useFeatureFlag('my_split') and receive a boolean. If we setup a multi-treatment split, we still have the ability to pass in the value that we'd like to check for with useFeatureFlag('my_split', { variantName: 'option2 '})
I know this is somewhat unaligned with the "everything is a string" approach with Split, but I did submit a feature request to allow Split users to specify the split "type" in the Split.io dashboard. It would be a neat thing to support in the future.
Thanks for sharing your snippet @besh - It might be useful for me too.