5 pitfalls of React Hooks you should avoid – Kent C. Dodds

0
3416
6 min read

The React community first introduced Hooks, back in October 2018 as a JavaScript function to allow using React without classes. The idea was simple – With the help of Hooks, you will be able to “hook into” or use React state and other React features from function components. In February, React 16.8 released with the stable implementation of Hooks.

As much as Hooks are popular, there are certain pitfalls which developers should avoid when they are learning and adopting React Hooks. In his talk, “React Hook Pitfalls” at React Rally 2019 (August 22-23 2019), Kent C. Dodds talks about 5 common pitfalls of React Hooks and how to avoid/fix them. Kent is a world renowned speaker, maintainer and contributor of hundreds of popular npm packages. He’s actively involved in the open source community of React and general JavaScript ecosystem. He’s also the creator of react-testing-library which provides simple and complete React DOM testing utilities that encourage good testing practices.

Tl;dr

  1. Problem: Starting without a good foundation
    Solution: Read the React Hooks docs and the FAQ
  2. Problem: Not using (or ignoring) the ESLint plugin
    Solution: Install, use, and follow the ESLint plugin
  3. Problem: Thinking in Lifecycles
    Solution: Don’t think about Lifecycles, think about synchronizing side effects to state
  4. Problem: Overthinking performance
    Solution: React is fast by default and so research before applying performance optimizations pre-maturely
  5. Problem: Overthinking the testing of React hooks
    Solution: Avoid testing ‘implementation details’ of the component.

Pitfall #1 Starting without a good foundation

Often React developers begin coding without reading the documentation and that leads to a number of issues and small problems. Kent recommends developers to start by reading the React Hooks documentation and the FAQ section thoroughly. He jokingly adds, “Once you read the frequently asked questions, you can ask the infrequently asked questions. And then maybe those will get in the docs, too. In fact, you can make a pull request and put it in yourself.”

Pitfall #2: Not using or (ignoring) the ESLint plugin

The ESLint plugin is the official plugin built by the React team. It has two rules: “rules of hooks” and “exhaustive deps.” The default recommended configuration of these rules is to set “rules of hooks” to an error, and the “exhaustive deps” to a warning. The linter plugin enforces these rules automatically. The two “Rules of Hooks” are:


  1. Don’t call Hooks inside loops, conditions, or nested functions
    Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders.
  2. Only Call Hooks from React Functions

Don’t call Hooks from regular JavaScript functions. Instead, you can either call Hooks from React function components or call them from custom Hooks.

Kent agrees that sometimes the rule is incapable of performing static analysis on your code properly due to limitations of ESLint. “I believe”, he says, “ this is why it’s recommended to set the exhaustive deps rule to “warn” instead of “error.” When this happens, the plugin will tell you so in the warning. He recommends  developers should restructure their code to avoid that warning.

The solution Kent offers for this pitfall is to Install, follow, and use the ESLint plugin. The ESLint plugin, he says will not only catch easily missable bugs, but it will also teach you things about your code and hooks in the process.

Pitfall #3: Thinking in Lifecycles

In Hooks the components are declarative. Kent says that this feature allows you to stop thinking about “when things should happen in the lifecycle of the component” (which doesn’t matter that much) and more about “when things should happen in relation to state changes” (which matters much more.)

With React Hooks, he adds, you’re not thinking about component Lifecycles, instead you’re thinking about synchronizing the state of the side-effects with the state of the application. This idea is difficult for React developers to grasp initially, however once you do it, he adds, you will naturally experience fewer bugs in your apps thanks to the design of the API.

Solution: Think about synchronizing side effects to state, rather than lifecycle methods.

Pitfall #4: Overthinking performance

Kent says that even though it’s really important to be considerate of performance, you should also think about your code complexity. If your code is complex, you can’t give people the great features they’re looking for, as you will be spending all your time, dealing with the complexity of your code.

He adds, “unnecessary re-renders” are not necessarily bad for performance. Just because a component re-renders, doesn’t mean the DOM will get updated (updating the DOM can be slow). React does a great job at optimizing itself; it’s fast by default.

For this, he mentions. “If your app’s unnecessary re-renders are causing your app to be slow, first investigate why renders are slow. If rendering your app is so slow that a few extra re-renders produces a noticeable slow-down, then you’ll likely still have performance problems when you hit “necessary re-renders.” Once you fix what’s making the render slow, you may find that unnecessary re-renders aren’t causing problems for you anymore.”

If still unnecessary re-renders are causing you performance problems, then you can unpack the built-in performance optimization APIs like React.memo, React.useMemo, and React.useCallback. More information on this on Kent’s blogpost on useMemo and useCallback.

Solution: React is fast by default and so research before applying performance optimizations pre-maturely; profile your app and then optimize it.

Pitfall #5: Overthinking the testing of React Hooks

Kent says, that people are often concerned that they need to rewrite their tests along with all of their components when they refactor to hooks from class components.

He explains, “Whether your component is implemented via Hooks or as a class, it is an implementation detail of the component. Therefore, if your test is written in such a way that reveals that, then refactoring your component to hooks will naturally cause your test to break.”

He adds, “But the end-user doesn’t care about whether your components are written with hooks or classes. They just care about being able to interact with what those components render to the screen. So if your tests interact with what’s being rendered, then it doesn’t matter how that stuff gets rendered to the screen, it’ll all work whether you’re using classes or hooks.”

So, to avoid this pitfall, Kent’s recommendation is that you write tests that will work irrespective of whether you’re using classes or hook. Before you upgrade to Hooks, start writing your tests free of implementation detail and your refactored hooks can be validated by the tests that you’ve written for your classes. The more your tests resemble the way your software is used, the more confidence they can give you.

In review:

  1. Read the docs and the FAQ.
  2. Install, use and follow the ESLint plugin.
  3. Think about synchronizing side effects to state.
  4. Profile your app and then optimize it.
  5. Avoid testing implementation details.

Watch the full talk on YouTube.

Read more about React

#Reactgate forces React leaders to confront community’s toxic culture head on

React.js: why you should learn the front end JavaScript library and how to get started

Ionic React RC is now out!

Content Marketing Editor at Packt Hub. I blog about new and upcoming tech trends ranging from Data science, Web development, Programming, Cloud & Networking, IoT, Security and Game development.