# Feature Flags in React with Flagged

When you are working in a big product, with multiple teams adding features and
doing continuos deployment it's common to need a way to hide certain unfinished
or unpolished parts of a UI from the users in production.

Or maybe you want to only show certain features to some users, maybe only to
paid users or employees of a company. Even it's possible that you want to hide
parts of the UI based on the role, e.g. only show admin features to admin users.

This is where enters Feature Flags, a technique to hide or show features based
on a flag, which is basically a boolean which tells the application if the
feature is enabled or not.

Let's see how we could show or hide React components based on those flags, for
doing this we are going to use a package called
[Flagged](https://github.com/sergiodxa/flagged), which is a super tiny library
to use this technique in React based applications.

## Hide Admin Only Components

Let's start with the simplest one, hide components intended to be available only
to admin users. Let's say we have a wiki application, this application shows to
the user the content along a button to edit it, but those edits should be
moderated and if you are an admin it will show another button to see pending
edits.

```js
import React from "react";
import EditButton from "./edit-button";
import ModerateButton from "./moderate-button";

function ContentPage({ content }) {
  return (
    <section>
      <header>
        <EditButton />
        <ModerateButton />
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

Something like that should work, right? But what happens when an non-admin users
access a page rendered by this component? It will see two buttons, the edit and
the moderate, and if the user tries to click the moderate button it will
probably got a rejection when trying to access the moderation page which is
probably a protected page already.

This is not ideal from the user perspective, we shouldn't show a button the user
can't use, to solve this let's use flagged.

```js
import React from "react";
import { FlagsProvider } from "flagged";

import ContentPage from "./content-page";

function App({ user }) {
  return (
    <FlagsProvider features={{ moderate: user.role === "admin" }}>
      <ContentPage />
    </FlagsProvider>
  );
}

export default App;
```

This will make the flag `moderate` enabled if the user has the role `admin` and
disabled in other cases.

Now we need to check the flag status in our component, in our case since we want
to hide `ModerateButton` completely if the user is not admin we could use the
`withFeature` high order component flagged gives us.

```js
import React from "react";
import { withFeature } from "flagged";
import Button from "./button";

function ModerateButton() {
  return <Button href="moderate">Moderate</Button>;
}

export default withFeature("moderate")(ModerateButton);
```

Now our component will only render if the flag `moderate` is `true`, if it's
`false` then `withFeature` will return `null` and avoid rendering at all.

This is useful in the case we want to render or not a component without a
fallback in case the feature is disabled.

## Paid Only Feature with Fallback

Let's say now we want to only let paid users be able to edit content in our
wiki, while free users will only be able to read the content, we could use an
approach similar to before and hide the edit button completely from free users,
however in this case it could be better to let the free users know this edit
feature exists and they need to pay to use it, this way users may be tempted to
pay us.

Let's start by adding a new flag.

```js
import React from "react";
import { FlagsProvider } from "flagged";

import ContentPage from "./content-page";

function App({ user }) {
  const features = {
    moderate: user.role === "admin",
    paid: user.role === "admin" || user.hasActiveSubscription
  };

  return (
    <FlagsProvider features={features}>
      <ContentPage />
    </FlagsProvider>
  );
}

export default App;
```

This will enable the `paid` features if the user is either an admin or has an
active subscription.

Now let's use the `Feature` component flagged gives use to provide an
alternative to the Edit button in case the user is not a paid one.

```js
import React from "react";
import { Feature } from "flagged";
import EditButton from "./edit-button";
import FakeEditButton from "./fake-edit-button";
import ModerateButton from "./moderate-button";

function ContentPage({ content }) {
  return (
    <section>
      <header>
        <Feature name="paid">
          {isPaid => (isPaid ? <EditButton /> : <FakeEditButton />)}
        </Feature>
        <ModerateButton />
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

This `Feature` component will let use know if the feature `paid` is enabled so
we could show two different components based on that. Our `FakeEditButton` could
simulate the `EditButton` and show a modal to convince the user to become a paid
one in order to use it.

We could also use the `Feature` component to replace the `withFeature` high
order component.

```js
import React from "react";
import { Feature } from "flagged";
import EditButton from "./edit-button";
import FakeEditButton from "./fake-edit-button";
import ModerateButton from "./moderate-button";

function ContentPage({ content }) {
  return (
    <section>
      <header>
        <Feature name="paid">
          {isPaid => (isPaid ? <EditButton /> : <FakeEditButton />)}
        </Feature>
        <Feature name="moderate">
          <ModerateButton />
        </Feature>
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

This way we could ditch the `withFeature` HOC, the only possible issue here is
not our `ContentPage` needs to know if `ModerateButton` should be behind a flag
or not, in the HOC approach it was the `ModerateButton` the only one aware of
the flag.

## Run Effects Based on a Flag

We saw how to use the high order component and the render prop API Flagged gives
us, both of those use internally the custom hook `useFeature` to detect if the
feature is enabled or not. This custom hook could also help use create custom
logic based on a flag.

Let say now want to track when a free user access a page, but we don't want to
track paid users, since they are paying we promising them anonymity in our
application.

Let's create a custom hook `useTracking` which will use our `useFeature` to
check if it should or not track the user.

```js
import React from "react";
import { pageview } from "../services/analytics";
import { useFeature } from "flagged";

function useTracking() {
  const isPaid = useFeature("paid");

  React.useEffect(() => {
    if (isPaid) return;

    pageview(window.location.pathname);
  }, [isPaid]);
}

export default useTracking;
```

Now let's use it in our `ContentPage` component.

```js
import React from "react";
import { Feature } from "flagged";
import EditButton from "./edit-button";
import FakeEditButton from "./fake-edit-button";
import ModerateButton from "./moderate-button";
import useTracking from "../hooks/use-tracking";

function ContentPage({ content }) {
  useTracking();

  return (
    <section>
      <header>
        <Feature name="paid">
          {isPaid => (isPaid ? <EditButton /> : <FakeEditButton />)}
        </Feature>
        <ModerateButton />
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

That's all, our tracking hook will only work for non-paid users.

## Hooks as a Low Level Primitive

We could also use the `useFeature` hook to replace the render prop component in
`ContentPage`.

```js
import React from "react";
import { useFeature } from "flagged";
import EditButton from "./edit-button";
import FakeEditButton from "./fake-edit-button";
import ModerateButton from "./moderate-button";
import useTracking from "../hooks/use-tracking";

function ContentPage({ content }) {
  const isPaid = useFeature("paid");
  useTracking();

  return (
    <section>
      <header>
        {isPaid ? <EditButton /> : <FakeEditButton />}
        <ModerateButton />
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

Even the `ModerateButton` could be hidden using the `useFeature` hook.

```js
import React from "react";
import { useFeature } from "flagged";
import EditButton from "./edit-button";
import FakeEditButton from "./fake-edit-button";
import ModerateButton from "./moderate-button";
import useTracking from "../hooks/use-tracking";

function ContentPage({ content }) {
  const isPaid = useFeature("paid");
  const isModerator = useFeature("moderate");
  useTracking();

  return (
    <section>
      <header>
        {isPaid ? <EditButton /> : <FakeEditButton />}
        {isModerator && <ModerateButton />}
      </header>
      <article>{content}</article>
    </section>
  );
}

export default ContentPage;
```

This will render `ModerateButton` only if `isModerator` is `true`.

## Final Words

As you could see above there are multiple cases in which feature flags flags is
useful and with [Flagged](https://github.com/sergiodxa/flagged) there are
multiple approaches you could take to detect if a flag is enabled and render a
component or run an effect.

Are you using feature flags in your project? Do you know another example where
it could be useful? Do you have any question about how Flagged or Feature Flags
works? Send me tweet to share your thoughts.