🏗️ How to rollout features to specific users in ReactJS
Tags: react, webdev, typescript, beginners
Published: 2023-07-21 10:40:16

## TL;DR
In this article I am going to show you how to activate specific features for specific users using feature flags in a ReactJS app.

Even though there are multiple services which would allow you to manage your feature flags, we are going to use SwitchFeat, a service that I am building open-source and in public.

**Why is this useful?**
- Gradually release features to subsets of users.
- Decouple deployments from releases.
- Safe guarding new feature with kill-switches.
- and many more...

---

## Can you help?
I am trying to increase the visibility of my repo, could you help me by adding a **star to the project**? It would help me so much and it would give a big boost to publish more articles weekly! 🤩

[https://github.com/switchfeat-com/switchfeat](https://github.com/switchfeat-com/switchfeat)

<img width="1000" src="https://media.giphy.com/media/QAsBwSjx9zVKoGp9nr/giphy.gif" />

---

## Let's get started! 🔥

First thing first, create a React app in Typescript

`npx create-react-app my-react-app --template typescript`

Let's install some common dependancies

`npm i --save @types/node @types/react @types/react-dom uuidv4`

Running these two commands already give you a working React app which we can start modifying as desired.

This is the default `App.tsx` which is going to hold our homepage:
``` javascript
const App : React.FC = () => {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
export default App;
```

Which looks like this:

![Default result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/og2yzkrfo776b1e0x35s.png)

To manage styles a bit more easily, we will use TailwindCSS, which allows to specify inline classes without going to touch css files.

> **I know this stuff Andy! Give me something new!**

---

## Let's protect our component ⛔

Now things become a bit more interesting. We are going to build a new component, `SuperCoolCard`, which is going to hold some functionality which we want to gate and make available only to a specific segment of users. 

Let's say that we want to show this card to users with an email address ending with `@switchfeat.com`.

For the purpose of this article, the component is going to be super simple: 

``` javascript
export const SuperCoolCard : React.FC = () => {
    return (
        <div className="rounded-lg shadow   
             bg-orange-500 p-10 mt-10">
            <div>Super cool feature </div>
            <button className="rounded-md bg-indigo-600 
                    px-3.5 py-2.5 font-semibold text-white 
                    shadow-sm hover:bg-indigo-500 
                    text-lg mt-4">Let's start</button>
        </div>
    );
}
```

In order to gate the access to this component to a specific user segment, we can use the SwitchFeat API as follows: 

``` javascript
 const [showNewCard, setShowNewCard] = useState<boolean>(false);
 const [userContext, setUserContext] = 
                   useState<{}>({ username: 'a@switchfeat.com' });
 
 useEffect(() => 
    const formData = new FormData();
    formData.append('flagKey', "new-card");
    formData.append('flagContext',  JSON.stringify(userContext));
    formData.append('correlationId', uuidv4());
    
    const evaluateFlag = () => {
      fetch(`http://localhost:4000/api/sdk/flag/`, {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Access-Control-Allow-Credentials": "true",
          "Access-Control-Allow-Origin": "true"
        },
        body: formData
      }).then(resp => {
        return resp.json();
      }).then(respJson => {
        setShowNewCard(respJson.data.match);
      }).catch(error => { console.log(error); });
    };

    evaluateFlag();

  }, []);
```

First of all, we add a state to the page which will hold the information regarding if the card component should be shown or not.
This is a React construct which forces a re-render of the component if such state changes, to show the latest data.

The `useEffect()` call is a side effect which, in this case, gets executed at first page load (or page refreshes). It is responsible of calling the SwitchFeat API via a POST Fetch request, to get the status of the requested flag based on the provided context. 

In this example, the user context provided is: `{email:'a@switchfeat.com'}`. 

For the purpose of this article, I put the user context in the state of the component, but this should really depend on the current user data in a real scenario.

Last step is going to beadding the reference to the new component in the page behind the "protected" state: 

``` javascript
return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"  href="https://reactjs.org"
          target="_blank" rel="noopener noreferrer">Learn React
        </a> 
        {showNewCard && <SuperCoolCard />}
      </header>
    </div>
  );
```

What's going to happen now, is that when there is a state change in the value of `showNewCard`, the whole component re-renders and the `SuperCoolCard` component will either show up or not based on the API response from SwitchFeat. Cool right!?

> SwitchFeat is under active development and I already planned to **release an SDK for NodeJS**, together with other languages over time. So the interaction with the API will be simplified even further.

---

## Behind the scenes 😎

The SwitchFeat API, upon receiving the request, runs the following checks: 

- Checks if the requested `flagKey` points to an existing flag.
- Checks if the requested flag has any rule.
- Evaluates all available rules and checks if the provided context (in this case `{email:'a@switchfeat.com'}`), matches at least one segment condition.
- Returns the match result or an error.

---

## The final results 🚀
 
Here it is how the page looks like by default having the flag disabled.

![Result with disabled flag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18kg6vxgfwhby11umtba.png)

Instead when the flag is enabled and there is a rule matching the context, our beautiful card can shine on the homepage!
 
![Result with enabled flag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sl8bnfq5z0x6oq1m2l7o.png)

What's even more important is that even if the flag stays enabled, but the context of the API call changes to something which is not matching any of the flag rules, the card will be removed from the DOM for those users.

So for example, providing a context like: `{email:'a@google.com'}`, the result is going to be:

![Result with no matching rule flag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w778r7qyk7j8dx0a2n68.png)

---

## Well done! 🙌

You can now sit and relax knowing that any feature you want to silently deploy and release at your own time, are safely protected by your feature flags!

---

## So.. Can you help? 😉

I hope this article was somehow interesting. If you could give a **star to my repo** would really make my day! 

[https://github.com/switchfeat-com/switchfeat](https://github.com/switchfeat-com/switchfeat)

<img width="1000" src="https://media.giphy.com/media/BPJmthQ3YRwD6QqcVD/giphy.gif" />