React Hooks is the functional paradise you’ve been waiting for

Stefan Nagey
Capbase Engineering
4 min readJan 12, 2019

We’ve all been there before. A react app that gets so unwieldy and becomes an utter mess of tangled lifecycle component interactions such that you can’t tell up from down, right from wrong (or write from read?), black from white.

I’m here to tell you that there is another way.

There is salvation!

React hooks, it’s where it’s at.

DISCLAIMER React hooks is still technically in alpha stage (16.8.0-alpha0 as of today, but that may change, use the `next` tag to be safe), so you shouldn’t use it for production, yada yada. That said, I am currently using it in a near production context, and apart from a brief misadventure with concurrent mode (more on that later) it is amazing.

I started off writing this as just a quick one-off. However, given that it’s now three thousand words later, I’m going to break this down into five parts, as follows:
1. The Basics: Problems in Class-based React and Functional Programming (this story)
2. Local state management using react hooks
3. Replacing Redux with React Hooks / Complex State Management with Hooks
4. Asynchronous Functional Programming & hooks with effects
5. Gotchas of Working with React Hooks & the new Concurrent Mode

The basics: Problems in Class-based React and their Functional Programming Solutions

If you’ve been around the react world for a while, you’ve probably seen people talk about functional components, without thinking too much about what they are, beyond, “they’re supposed to be better.” However, like eating your vegetables, you might not have actually done it.

React’s lifecycle model can be quick and satisfying at first, but just like real world spaghetti, it will make you put on weight and lead to long-term problems.

In classic React, you would build each component as an object, and that component would get initialized with it’s constructor, and then you would get calls to methods like didComponentUpdate, willComponentUpdate, componentReceivedProps, render, and so on, and so forth.

A relatively straightforward explanation of the spaghetti methods of classic react programming

Add on top of this something like redux where you have a global shared state that any component can connect to, access, and update (which will trigger a new round of updates), well, I’m sure you can see where you can start to run into some problems. All of these calls flying back and forth will very quickly turn into spaghetti, and can turn what should be a relatively straightforward debugging process turn into a mess of unintended behaviors, side effects, and consequences.

Functional programming in React can help to counteract all of that. Think of it as the Keto or Paleo alternative to the classic spaghetti model.

What is functional programming?

Functional programming (FP) in terms of React can be thought of very very simply. Everything is a function. No objects apart from Javascript objects, which you can — and should — treat like classic C structs. When you write a component, it’s a function. It receives arguments (as props), and it returns JSX.

When you write a functional component, your code runs straight through, one statement to the next. Race conditions are rare, and you can keep your code small and easy to understand.

There are no lifecycle methods to worry about, no complex internal state (because there is no state that persists from one run of the function to the next).

It drastically reduces the complexity of your code.

Now, I can hear some of you crying that it’ll make life harder if you can’t track state, and you can’t do things asynchronously, and, well, that’s where hooks come in. More on that later.

Writing Functional React

When you write functional react, all of your components are plain functions. They will receive their props as an argument, and they must return JSX.

The base of your component is your JSX, not much different than HTML. If the component gets too big, you can split it into smaller components, it’s as easy as:

const MyNewComponent = () => (
<div>
<p> some markup </p>
</div>
);

and then you can just call place that <MyNewComponent /> anywhere in your code you like (provided that it’s defined in your scope).

This also makes your code easier to test — simple inputs, simple outputs.

Putting it to use and moving on

In this part, you’ve seen why functional programming is important and what some of the Anti-patterns of writing React code using the traditional class-based approach are, and how functional, stateless components can help you overcome this.

In the upcoming parts of this series, we’ll take a look at how you can use state in a stateless component; how we can use react’s useContext and useReducer hooks to manage a complex state tree to replace flux, redux, and the connect/dispatch pattern thereof; working with async tasks and using async/await with react hooks and the useEffect hook; and finally the gotchas of working with React hooks and functional react.

About the Author

Stefan Nagey is Co-Founder of Capbase and Dharma. In a previous life he has variously promoted motion pictures, been a diplomat and registered foreign agent, and run payment processing in the online gambling space. He variously writes about engineering and the headaches of being a startup founder in the 21st century.

--

--

Stefan Nagey
Capbase Engineering

Data geek. Capbase.com and Dharma.ai Co-Founder. Passionate about scalability, governance, cycling, and poker.