image credit: Efe Kurnaz

Do you need React Hooks?

last updated: Jul 25th, 2019


How many times have you put your head down to work on a big project and -- in what feels like the blink of an eye -- several months or even years (ouch) pass by and you realize you haven't come up for air.

It can be difficult to keep current with the latest developments in the JavaScript (and React) ecosystem.

Well... answer me this, busy React developer:

  1. does writing boilerplate code make you afraid of carpal tunnel syndrome?
  2. does your heart skip a beat when you think of stateless functional components?
  3. have you been too busy to check out new React developments lately?

Stop what you're doing right now if you answered 'Yes' to all three questions!

You need React Hooks in your life.

Let me explain further.

I work on a couple of large React projects. One, in particular, predates create-react-app; it's big and old and fragile and -- honestly -- not done very well. In my defense, I was learning as I went along and it was built during a time when there simply were no Best Practices for React development.

For the past year or two I've wanted to update the codebase... fix flaws, clean it up, bring it up to date so I can leverage newer techniques, libraries, and language features, etc. But the task has been daunting to say the least.

Just recently, I finally bit the bullet (so to speak) and am going through the painful process of upgrading the infrastructure, which involves moving it to create-react-app, upgrading several libraries to latest (most notably: react-router), dropping Immutable.js, fixing new type errors, etc.

And trust me, it is painful -- but worth it for the prospect of being able to use React Hooks, which was the thing that pushed me over the edge.

React Hooks make React code so much easier to read and write. And I hope they also make React with TypeScript more approachable for beginners.

For comparison, here's an example of a modest React component, written as a stateless functional component (without hooks) in TypeScript:

import * as React from 'react';import { compose } from 'recompose';import { connect } from 'react-redux';import { withTranslation } from 'react-i18next';import { getBar } from './selectors';import { doSomething } from './actions';export type OwnProps = {  foo: string;};const _SomeComponent = ({ foo, bar, onClick, t }: Props) =>  <div    className={ foo }    onClick={ onClick }  >    <span>{ t(bar) }</span>  </div>;type StateProps = {  bar: string | null;};type DispProps = {  onClick: () => void;};const mapStateToProps = (state: State): StateProps => ({  foo: getFoo(state),});const mapDispatchToProps = (dispatch: Function): DispProps => ({  onClick: () => dispatch(doSomething()),});export type Props = OwnProps & StateProps & DispProps & WithTranslation;export const SomeComponent = compose<Props, OwnProps>(  withTranslation(),  connect<StateProps, DispProps, OwnProps>(mapStateToProps, mapDispatchToProps),)(_SomeComponent);

I've written that bittersweet pattern hundreds of times.

Writing React feels so good... yet, there is so much wrong with the code above. Specifically, it's unnecessarily complex; it's got bits of logic and type info strewn all over the file as if an explosion had scattered it all; and, if you look at the render tree, you'll see some nasty nesting -- especially for larger components that compose many more HOC's.

Now take a look at how elegant the same component is when we rewrite it with React hooks:

import * as React from 'react';import { useCallback } from 'react';import { useSelector, useDispatch } from 'react-redux';import { useTranslation } from 'react-i18next';import { getBar } from './selectors';import { doSomething } from './actions';export type Props = {  foo: string;};export const SomeComponent = ({ foo }: Props) => {  const { t } = useTranslation();  const bar = useSelector(getBar);  const dispatch = useDispatch();  const onClick = useCallback(() => dispatch(doSomething()), [ dispatch ]);  return (    <div      className={ foo }      onClick={ onClick }    >      <span>{ t(bar) }</span>    </div>  );};

How many differences can you spot?



Wrap up

I hope this was as much of an eye opener for you as it was for me.

I'm not rewriting all my legacy components right away... but definitely all new components from now on are going to use hooks and I'll rewrite old ones where it makes sense.

Learning More

Read more about hooks in the official React documentation: Introducing Hooks

Also check out my new video series where I show you how I build React components. (using React hooks starting with Episode 2 - Star Rating)

Level up Your React + Redux + TypeScript

for free with articles, tutorials, sample code, and Q&A.