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

React integration for feature flags #154

Merged
merged 9 commits into from Dec 11, 2020
Merged

React integration for feature flags #154

merged 9 commits into from Dec 11, 2020

Conversation

ghost
Copy link

@ghost ghost commented Dec 9, 2020

Changes

I have created a package that can be imported into React applications, which to start with exposes a React hook useFeatureFlags in order to close PostHog/posthog#1997. This package can be easily extended to export additional hooks or other useful components. It might be worth splitting this off into its own repo so that you can have independent npm versioning and changelogs.

If you are happy with the implementation I will add the relevant tests. I would also be more than happy to build out additional React hooks/components if you have some in mind.

useFeatureFlags functionality

  • Fetches the active flags, and returns an object containing the flags enabled for the user
  • Optionally pass a refreshInterval to refresh the enabled feature flags
  • Optionally pass a sendEvent = false to turn off event sending for the isFeatureEnabled calls
  • I did not implement throttling for the send events as mentioned at Allow toggling of feature_flag_called #108 (comment) because this seemed like an edge case

Integration details

  1. Wrap your React app with PostHogProvider, passing it an instance of your initialised PostHog client. This creates an app-wide context to store the client, and other data (in this case, data fetched regarding the feature flags).
import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react";

posthog.init("API_KEY", {
  api_host: "HOST"
});

ReactDOM.render(
  <React.StrictMode>
    <PostHogProvider client={posthog}>
      <App />
    </PostHogProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
  1. In the component(s) that need to use feature flags, call the useFeatureFlags hook and do something useful with the return value.
import React from "react";
import { useFeatureFlags } from "posthog-js/react";

export default function ExampleComponent() {
  const { enabled: enabledFlags } = useFeatureFlags({
    refreshInterval: 10, // Refresh enabled flags every 10 seconds
    sendEvent: false, // Disable event sending when checking feature enabled status
  });

  return enabledFlags.secretFeature ? (
    <div>Display secret feature component</div>
  ) : (
    <div>Display default component</div>
  );
}

Additional context around the reasoning for this implementation:

I originally tried to extend the existing posthog-js package to export React hooks. However, I did not want to affect the dependencies of non-React users of the package.

I tried to follow apollo-client’s implementation, because that package supports importing non-React functions (when React is not a dependency), even though the same package also exports React hooks. To that effect, I tried setting external: [‘react’] in rollup.config.js and adding the following to package.json:

"peerDependencies": {
    "react": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
    "react": {
        "optional": true
    }
},

However, I found that the built module.js would still include var react = require(‘react’) at the top of the file. Not good for non-React users. Looking closer, apollo-client actually achieves what I described by having a complicated build process which I did not think was reasonable to implement.

At that point I realised it would be more straight-forward to make a second package which would be imported for e.g. import { useFeatureFlags} from ‘posthog-js/react. That would give us a clean separation of dependencies.

Checklist

  • Tests for new code (if applicable)
  • TypeScript definitions (module.d.ts) updated and in sync with library exports (if applicable)

@jamesefhawkins
Copy link
Contributor

@stevenphaedonos heroic effort, thank you so much! We'll take a look 👍

Copy link
Contributor

@macobo macobo 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 doing this! Really appreciate the depth you've gone into here and this looks great. Added one comment here that might help simplify things.

I think it makes sense to manage this outside of the posthog-js repo. Since this is your sweat and blood, do you want to create one yourself under your own account? :)

react/src/hooks/useFeatureFlags.ts Outdated Show resolved Hide resolved
@ghost
Copy link
Author

ghost commented Dec 9, 2020

Thanks for doing this! Really appreciate the depth you've gone into here and this looks great. Added one comment here that might help simplify things.

I think it makes sense to manage this outside of the posthog-js repo. Since this is your sweat and blood, do you want to create one yourself under your own account? :)

I personally think it makes more sense to place the new posthog-js-react repo under the control of the PostHog GitHub account. I can create a PR for this initial setup + first hook under that repo. I think there is a great opportunity to expand out your React tooling, and I would be more than happy to continue contributing. As well, I would imagine that you want control of npm publishing for this too. Let me know if you would prefer the alternative and I will set things up.

@macobo
Copy link
Contributor

macobo commented Dec 9, 2020

Thanks for the quick turnaround. We discussed it internally and I think we'll indeed publish this as part of this package.

Great job! I'll look to get this merged and published over the next couple of days. If you like, please email yakko[@]posthog[.]com to get some posthog SWAG. :)

@macobo macobo merged commit d9ef197 into PostHog:master Dec 11, 2020
@davidfurlong
Copy link

Can't seem to figure out how to consume this via a library. Is it part of posthog-js?

@curtvict
Copy link
Contributor

curtvict commented Feb 3, 2023

Can't seem to figure out how to consume this via a library. Is it part of posthog-js?

Yes, but you need to access it via posthog-js/react.

import { PostHogProvider, useFeatureFlags } from "posthog-js/react";

@curtvict
Copy link
Contributor

curtvict commented Feb 3, 2023

@macobo The react offering here is pretty small, just a Provider & Hook, but still I feel that it deserves some documentation published to https://posthog.com/manual/feature-flags

I stumbled upon this hook today and it was able to resolve a serious bug I encountered with our own homebrewed hook.

@calvinwoo
Copy link

Looks like they expanded the React SDK and wrote new docs: https://posthog.com/docs/libraries/react

@tboulis
Copy link

tboulis commented Aug 23, 2023

Was this removed or consolidated into an existing hook?
The useFeatureFlags hook is not exported from `posthog/js-react':

image

I'm using the latest version:

@neilkakkar
Copy link
Collaborator

@tboulis
Copy link

tboulis commented Aug 23, 2023

https://posthog.com/docs/libraries/react#feature-flags

There's nothing in the docs about listening to feature flag changes. Which is what this PR does, am I missing something?

@neilkakkar
Copy link
Collaborator

my bad, didn't know what you were looking for here.

You can still use posthog.onFeatureFlags() to listen for when flags are reloaded, and posthog.reloadFeatureFlags() to reload flags. There isn't a hook equivalent to this. However, all existing hooks do use this under the hood, and you can add your own listeners for when flags change, just check the implementation.

@tboulis
Copy link

tboulis commented Aug 23, 2023

Got it, thanks!

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.

React integration for feature flags
7 participants