Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] useTreatment and useTreatmentWithConfig hooks #69

Open
besh opened this issue Aug 30, 2021 · 8 comments
Open

[Feature request] useTreatment and useTreatmentWithConfig hooks #69

besh opened this issue Aug 30, 2021 · 8 comments

Comments

@besh
Copy link

besh commented Aug 30, 2021

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!

@chillaq
Copy link

chillaq commented Aug 30, 2021

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 useTreatments hook
    const treatments = useTreatments([featureName]);
    return isReady ?
    renderContent(treatments[featureName], props) : // Use the treatments and configs.
    ; // 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;

@besh
Copy link
Author

besh commented Aug 31, 2021

@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.

@besh
Copy link
Author

besh commented Aug 31, 2021

Draft PR: #70

@EmilianoSanchez
Copy link
Contributor

EmilianoSanchez commented Sep 1, 2021

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.

@besh
Copy link
Author

besh commented Sep 1, 2021

@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.

@EmilianoSanchez
Copy link
Contributor

EmilianoSanchez commented Sep 10, 2021

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.

@besh
Copy link
Author

besh commented Sep 28, 2021

@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.

@WillsB3
Copy link

WillsB3 commented Sep 12, 2023

Thanks for sharing your snippet @besh - It might be useful for me too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants