Everywhere I look lately, I see React Hooks. It’s the new trend that’s taken over the developer world. Hooks are functions that let you hook into state and lifecycle features from functional components. The value here is that they let you use React without classes. This makes for shorter, cleaner code.
Use React Hooks to Simplify Your Code
In this quick tutorial, you’ll be using the Split React SDK, the React Hooks API, and this Split repo to create a basic to-do list app with React, and optimizing it with Hooks. Your goal here is to create a to-do list app that allows for controlled rollout with feature flags.
In a typical React application, data is passed top-down (parent to child) via props, but this can become unorganized and overwhelming for certain types of props that are required by many components. Context allows components to access shared functionality without having to explicitly and manually pass props through every level of the component hierarchy.
In my previous blog post, I implemented a to-do list app in the “classic” React style, with a higher-order component — <SplitTreatments>
, provided by the Split SDK -and props being passed down. In that tutorial I used a prop called allowDelete
in my render function that was passed down from the parent component:
renderContent(deleteTreatment) {
const allowDelete = deleteTreatment.treatment === "on";
return (
<div className="todoListMain">
<div className="header">
<form onSubmit={this.addItem}>
<input
ref={(a) => (this._inputElement = a)}
placeholder="Enter Task"
></input>
<button type="submit">Add</button>
</form>
</div>
<TodoItems
entries={this.state.items}
allowDelete={allowDelete}
delete={this.deleteItem}
/>
</div>
);
}
JSXHowever, it’s better to avoid passing props down from parent components, if you can avoid it. Imagine a large, complex application with a deep component hierarchy — you’d find yourself having to pass props down through many layers of intermediary components that don’t care about the props themselves (a problem known as prop drilling). That’s where the idea of Context comes into play.
Context lets you create a wrapper around your whole application that contains the shared functionality that your lower-level components want access to — your shared context. Any component that cares about this context can access it, via a useContext
hook. Think of this as a shortcut that lets the component reach back up to get what it needs when it needs it. It’s a manageable way for things at the bottom of the hierarchy to know about the thing at the top.
You’ll use this Context facility to provide shared access to your feature flagging implementation. In the previous post, I wrapped my top-level TodoList
component using withSplitFactory
. This set up a SplitContext
context provider at the top of our component hierarchy, which was then available to any nested component that needed to know about feature flags.
import { SplitTreatments, withSplitFactory } from "@splitsoftware/splitio-react"
export default withSplitFactory(sdkConfig)(TodoList);
JavaScriptYou’ll use the same setup in the hook-based implementation of this app, but instead of having to use an extra higher-order component every time you want to access this Context, you instead just use the useContext
hook. This is the functional way of making the connection back to the top of the application where you are managing Context:
import { useContext } from "react";
import { SplitContext } from "@splitsoftware/splitio-react";
export default function TodoItems({ deleteItem, entries }) {
const { client } = useContext(SplitContext);
const deleteTreatment = client.getTreatment(DELETE_TREATMENT);
const allowDelete = deleteTreatment === "on";
// ...
}
JSXIf you want to clean this up, you can extract some of that into a function in a separate file:
// useTreatment.js
import { useContext, useDebugValue } from "react";
import { SplitContext } from "@splitsoftware/splitio-react";
export default function useTreatment(treatmentName) {
const { client } = useContext(SplitContext);
const treatmentValue = client.getTreatment(treatmentName);
useDebugValue(`${treatmentName}: ${treatmentValue}`);
return treatmentValue;
}
JSX// ToDoItems.js
export default function TodoItems({ deleteItem, entries }) {
const allowDelete = useTreatment(DELETE_TREATMENT) === "on";
}
JSXIn this code, you need to go back up and reach for the shared context called SplitContext (provided by the React Split SDK). When you call withSplitFactory
, it’s wrapping everything with that context provider. That’s at the top of the hierarchy. In your lower-level component, you want to use that thing, so you call useContext. You want access to SplitContext
, specifically, which will give you access to the Split SDK. This will give you all the feature flag information your lower-level component needs regarding the state of the treatment. If it’s on, you allow delete, and if off, you do not allow delete.
This line, const allowDelete = useTreatment(DELETE_TREATMENT) === 'on';
, takes care of all the feature flag plumbing. All you need to do is call the function. Whenever you render the todoitems
component, you will use the useTreatment
hook to pull the feature flag information inside the component and then allow the user to delete if it’s equal to on. The parent component doesn’t have to pass anything down anymore. It uses the hook to magically know the state of the flag.
Learn More About React, Hooks, and Feature Flags
With this approach, you not only have less code but also cleaner code. It lets you utilize functions like useContext to get information you need when you need it, and avoiding prop drilling (having to pass props down through each layer).
Using hooks rather than the standard class-based components is less boilerplate, easier to test, and you don’t need to always think of the internal state of the component.
Here’s a link to the entire repo. If you’re interested in learning more, check out these posts:
- Learn how to set up Feature Flags with React in 10 Minutes
- Read up on Testing your Styled Components with React
- Watch this video on Feature Flag Best Practices
- Read our Essential Guide to Feature Flags
- Check out all the cool things you can do with Split’s free edition.
Be sure to follow us on Twitter @splitsoftware, and subscribe to our YouTube channel!
Get Split Certified
Split Arcade includes product explainer videos, clickable product tutorials, manipulatable code examples, and interactive challenges.
Switch It On With Split
The Split Feature Data Platform™ gives you the confidence to move fast without breaking things. Set up feature flags and safely deploy to production, controlling who sees which features and when. Connect every flag to contextual data, so you can know if your features are making things better or worse and act without hesitation. Effortlessly conduct feature experiments like A/B tests without slowing down. Whether you’re looking to increase your releases, to decrease your MTTR, or to ignite your dev team without burning them out–Split is both a feature management platform and partnership to revolutionize the way the work gets done. Switch on a free account today, schedule a demo, or contact us for further questions.