- Problem: Starting without a good foundation
Solution: Read the React Hooks docs and the FAQ
- Problem: Not using (or ignoring) the ESLint plugin
Solution: Install, use, and follow the ESLint plugin
- Problem: Thinking in Lifecycles
Solution: Don’t think about Lifecycles, think about synchronizing side effects to state
- Problem: Overthinking performance
Solution: React is fast by default and so research before applying performance optimizations pre-maturely
- 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:
- 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.
- Only Call Hooks from React Functions
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.
The question is not "when does this effect run" the question is "with which state does this effect synchronize with"
useEffect(fn) // all state
useEffect(fn, ) // no state
useEffect(fn, [these, states])
— Ryan Florence (@ryanflorence) May 5, 2019
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.
- Read the docs and the FAQ.
- Install, use and follow the ESLint plugin.
- Think about synchronizing side effects to state.
- Profile your app and then optimize it.
- Avoid testing implementation details.
Watch the full talk on YouTube.