Adam Boro Front-End Developer • adamboro.com

React Hooks — let’s not get too attached

4 min read 1134


After the React team announced the proposal of a new feature called Hooks at React Conf 18, there was a strange reaction in the React community: a flurry of tutorials describing how to use it, as if it was already in React core.

What is explicitly described as “a new feature proposal” was treated by some as a feature announcement. Clearly, there’s too much hype and “let’s rewrite everything right now” attitude, as Dan Abramov of the React team remarked:

So let’s take a chill pill, not even bother with the proposed API, and ponder how React got to this point.

If you’d rather see the code and refactor your app to use Hooks right now, the official docs are an excellent starting point.

In one of the first conference talks about React, Pete Hunt uses the word hooks to refer to methods of React.Component, which allow the user to provide custom update logic — to hook into React’s internals and tweak their behaviour. The new feature proposal is introducing hooks in a similar sense — as a way of interacting with React by hooking your code into the React’s engine.

This idea of using functions instead of inheriting from classes plays well with the functional and declarative spirit of React. Because class-based components suffer from the old banana-gorilla-jungle problem, as described by Joe Armstrong:

the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

With React.Component, very often all you need is state or a ref, but what you get is a collection of methods you’ll never use and the necessity of writing the dreaded this keyword (which is an anagram for you know what). Basically, Hooks are a proposal to ditch the classes and instead of inheriting from React, hook into React.


How to React without classes

The class-based API of React has been a problem for some time now. The ES6 classes themselves are not really classes (just syntactic sugar masking prototypal inheritance), they don’t compose well, and the usage of this keyword creates binding issues, especially when performing asynchronous operations.

So the search for class-less React development was on. Maybe the most notable project — now discontinued because of the introduction of Hooks — is recompose (the first example in the docs is providing a state to a function component). However, recompose is making heavy use of the Higher Order Component pattern, which unfortunately creates a hard to read and false hierarchy in the render tree.

Another example is Reactions Component, which uses another very popular pattern for making the class components more composable — Render Prop. The problem here is that a user first has to be pretty familiar with class-based React API to make some sense of how Reactions Component is to be used.

There are also cool projects that use the new ES6 Proxies to manage state, like react-easy-state or — in a more lightweight and experimental way —react-recollect. I recommend the article about the latter, which is a nice dive into how a super-readable and self-explanatory state management can be achieved. Sadly, the support for ES6 Proxies is far from ideal.

Currently, the Hooks implementation allows for replacing almost all of class-based component’s functionality (Hook equivalents for componentDidCatch and getDerivedStateFromErrorare to be added soon), so after they’re added to React, the search can be called off. Classes in React aren’t going anywhere anytime soon, but it’s clear that React team envisions a class-free future for the library.

Just one kind of component, please

The dichotomy between class and function components is an unnecessary burden for a user. I tend to regard a function component as a kind of lightweight little brother of the full-fledged class component — also, the distinction plays nicely with the presentational and container component pattern. But when I imagine learning React now, I think it’d be a bummer that a decision about using state or not (the most basic feature of React) has to be made before even starting to write the component.

It’s a bit like synchronous vs. asynchronous functions: async/await and Promises help us escape callback hell, but why should a programmer have to care if an operation is async or not in the first place? For me at least, Hooks are a much more understandable abstraction than class Something extends React.Component— how do I know what’s lurking in the jungle that I have to bring along with the setState functionality?

Even more declarative and functional future

React prides itself on being declarative, but using lifecycle methods is quite imperative — a classic example is duplicated code in componentDidMount and componentDidUpdate methods. Using Hooks, that can be achieved with useEffect function (there’s a great example of how Hook’s declarative API beats lifecycle methods’ imperativeness in the official documentation).

Drop the “Stateless”, just “Functional Components“.

With Stateless Functional Components, React moved more in the direction of functional programming. Hooks are a move even further in that territory, as they enable building full-featured React apps without the use of classes, but with functions only.

When the proposal is finalized, it will be the biggest change to how React apps are developed since the launch of the library. Today’s nifty patterns like Higher Order Components or Render Prop will seem quirky or even hacky (because they introduce a false hierarchy). The familiar class App extends React.Component with its list of lifecycle methods will be a thing of the past, and if it wasn’t for JSX syntax, a piece of code might not even look like a React component at a first glance.

But until then, let’s not get too attached to the proposed API and focus on writing code using cool, stable features.

Further reading

Plug: LogRocket, a DVR for web apps

https://logrocket.com/signup/

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.

Adam Boro Front-End Developer • adamboro.com

Leave a Reply