Skip to content

feat (Hooks): Add useFeature hook #28

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

Merged
merged 12 commits into from
Mar 10, 2020
Merged

feat (Hooks): Add useFeature hook #28

merged 12 commits into from
Mar 10, 2020

Conversation

jamesopti
Copy link
Contributor

@jamesopti jamesopti commented Mar 4, 2020

Summary

This PR adds a React Hook called useFeature, enabling feature usage (with variables) via the hooks interface.

The API designed here is intended to be feature complete with the <OptimizelyFeature> component.

Justification - Why add hooks?

Despite just being the new hotness in the React world, there are a couple good reasons to supporting the hooks paradigm in this SDK:

  • Easy use of features/variables outside the context of JSX markup
  • Allow consumers to avoid using class components (mostly in the interest of bundle size)
    • This could also be done by rewriting <OptimizelyFeature> as a functional component that itself leverages built in React hooks for state management

TODO

  • Update hook to return a third argument, clientReady, which will indicate whether or not the client is ready.
  • Add more tests for usage of the options and overrides

Example Usage

Directly from the README update:

arguments

  • feature : string Key of the feature
  • options : Object
    • autoUpdate : boolean (optional) If true, this component will re-render in response to datafile or user changes. Default: false.
    • timeout : number (optional) Rendering timeout as described in the OptimizelyProvider section. Overrides any timeout set on the ancestor OptimizelyProvider.
  • overrides : Object
    • overrideUserId : string (optional) Override the userId for calls to isFeatureEnabled for this hook.
    • overrideAttributes : optimizely.UserAttributes (optional) Override the user attributes for calls to isFeatureEnabled for this hook.
import { useEffect } from 'react';
import { useFeature } from '@optimizely/react-sdk';

function LoginComponent() {
  const [isEnabled, variables] = useFeature('feature1', { autoUpdate: true }, { /* (Optional) User overrides */ });
  useEffect(() => {
    document.title = isEnabled ? 'login1' : 'login2';
  }, [isEnabled]);

  return (
    <p>
      <a href={isEnabled ? "/login" : "/login2"}>
        {variables.loginText}
      </a>
    </p>
  )
}

AutoUpdate

A utility was added to help manage auto updates of the feature and it's variables in autoUpdate.ts. Eventually, this utility can be used in a useExperiment hook.

Additionally, the useFeature and useExperiment hooks could then handle all the state management and auto update logic for <OptimizelyFeature> and <OptimizelyExperiment>, allowing those to just be thin wrapper components.

Test Plan

Minimal unit tests have been added to test the base case(s) here. Additional testing of the optional parameters will be added once this overall approach is agreed upon.

Note: Until we upgrade to React 16.9, there will be errors in the hooks.spec.tsx unit tests about not wrapping state setting test actions in act(). React 16.9 introduces async support for act(), which will allow us to wrap our invocation of await client.onReady()

Issues

Addresses #6

@jamesopti jamesopti added the rfc label Mar 5, 2020
@jamesopti jamesopti force-pushed the james/use_feature_hook branch 2 times, most recently from 9625b2f to 2242064 Compare March 5, 2020 00:27
@mikeproeng37 mikeproeng37 requested a review from mjc1283 March 5, 2020 00:32
@jamesopti jamesopti force-pushed the james/use_feature_hook branch from 2242064 to 318f094 Compare March 5, 2020 01:02
Copy link
Contributor

@mjc1283 mjc1283 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, no big objections, just questions, mainly the one about how/when optimizely is falsy.

I guess this means we drop support for React <16.9, is that right?

Allow consumers to avoid using class components (mostly in the interest of bundle size)
This could also be done by rewriting as a functional component that itself leverages built in React hooks for state management

Interesting, I wonder how much bundle size we could save by rewriting all our classes as hooks.

@jamesopti jamesopti force-pushed the james/use_feature_hook branch from 318f094 to daa2eaf Compare March 5, 2020 17:56
@jamesopti jamesopti force-pushed the james/use_feature_hook branch from 777f4e2 to dfccaf7 Compare March 6, 2020 17:49
@jamesopti jamesopti requested a review from mjc1283 March 6, 2020 19:00
Copy link
Contributor

@mjc1283 mjc1283 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a few small suggestions about docs and logging.

Copy link
Contributor

@circAssimilate circAssimilate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be so great to use, @jamesopti and really change the speed at which we can ship / cleanup feature flags in the frontend. Requesting changes for some answers but nothing I see blocking thus far.

@jamesopti jamesopti removed the rfc label Mar 9, 2020
Copy link
Contributor

@circAssimilate circAssimilate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the info @jamesopti!

@jamesopti jamesopti force-pushed the james/use_feature_hook branch from 3e415a6 to 657a160 Compare March 10, 2020 22:41
@jamesopti jamesopti merged commit 5652dc9 into master Mar 10, 2020
@jamesopti jamesopti deleted the james/use_feature_hook branch March 10, 2020 23:38
jamesopti pushed a commit that referenced this pull request Mar 15, 2020
…at uses useFeature hook (#32)

Summary
Updates <OptimizelyFeature> to be a functional component that

Also adds support for userId and userAttribute overrides.

Addresses #30

Release
Is this a breaking change? In theory the logic should behave the same, as #28 was designed to implement the same logic as <OptimizelyFeature>.

Timing wise, when isServerSide is false, the state setting of the correct values of the feature/variables in useFeature happens in a second chained thennable, rather than the first.

I dont think this should be considered a breaking change (and thus warrant a major release), but I wanted to point it out.
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

Successfully merging this pull request may close these issues.

3 participants