React hooks best practices in 2020

4 min


Hooks have become a part of React relatively recently, but they already have a major impact on how developers solve various problems with state management and more. But to take full advantage of React hooks requires experience. But while there may be some truth to the saying “no pain, no gain”, it doesn’t mean that you have to be the one to suffer. Through my own experience with hooks, I was able to come up with a lot of React hooks best practices so that you can get it right from the start.

Hooks in React made their debut at the beginning of 2019 and quickly gained popularity among React developers. Thanks to hooks, one could create stateful components without JavaScript classes and extending the React.Component. Hooks made our code simpler, more concise and readable. 

Getting rid of the classes made a lot of the boilerplate code disappear. For example, there is no longer a need to use the constructor and call super with props every time. There is also no need to bind methods or think about what this is at the moment. 

When using hooks, it is worth remembering a few rules, so that the code works as expected and is understandable to others. In this article, I will tackle two of them – useState and useEffect.

React hooks best practices – basics

I hope you already know this one, but I must mention it: Hooks cannot be called conditionally. You cannot put them in loops or nested functions inside your component. 

So what to do if you want to call a hook conditionally? Just put the condition inside your hook. 

Why is this so important? Hooks can be called multiple times in a given component and React operations are based on the order in which they are called. Not following this would introduce bugs to your application and fatal errors.

Fortunately, there is an eslint plugin created by React team which enforces you to follow this rule. It is called eslint-plugin-react-hooks and you can find it on npm. If you use Create React App for your application, it is installed by default. 

This plugin will work not only with React hooks but also with every custom hook. But for this to happen, you have to follow a specific convention – the hook name must start with use.

You can install the eslint-plugin-react-hooks plugin using the popular npm package manager

Pitfalls with the useState React hook

As I mentioned before, when using React hooks (and generally in programming), it is worth sticking to well-known conventions. When naming values from useState, it is assumed that the elements are called:

By doing so, you will be able to easily find functions linked to the state they update and your code will be consistent across the application.

The useState hook is great for storing the state for simple values such as booleans or form inputs. Unlike the state from classes, you are not limited to a single object. With useState you can (and you should) create separate values for each case.

For example, when working with form fields, instead of keeping user info in one state like this:

It’s better to create separate fields for each case:

Of course, there is no strict limit here and useState can indeed store objects, but there is a thing you need to remember. In class components, when you update state using this.setState, it is merged with the old one. With useState, the update function replaces the old state with a new one; there is no merging at the end. Take a look at this example:

If you updated the state like this, you would lose all your previous data. Don’t worry, there is a way to handle it. Similar to the this.setState class, instead of just passing new values, you can pass a function that receives the previous state. So you could do something like this:

Or you could do it with the spread operator:

One more important thing to note here. When you are updating values based on the previous state, you shouldn’t do it that way: 

Do you know where the problem is? State updates work asynchronously, so you should never rely on the previous values in this manner. Instead, you should always use a function, even when not dealing with objects.

See also: React state managent: React hooks vs Redux 

useEffect – one React hook to rule them all

The useEffect hook allowed for logical separation of functionalities in the component, depending on what they do, instead of when they should occur. In the class, we had to keep unrelated functionalities in given lifecycle methods. With useEffect, we can split our code into smaller chunks. And just like with useState, you should not worry about calling useEffect several times for each case.

When working with useEffect, in most cases you want to include a dependencies list. Why? Let’s say you want to create a timer in your application. You call the setInterval function inside useEffect to update the timer variable every 1000 ms.

See also: React component lifecycle with hooks

By default, useEffect runs on every render. So when you update your component state inside useEffect, state update triggers re-render. Then, useEffect runs again, which updates the state and it goes infinitely. Or at least until your browser or API crashes. Luckily for us, the React team thought about it and added an eslint rule, which reminds one of this. It is called exhaustive-deps and it is included with eslint-plugin-react-hooks.

But in this case, dependency with a timer would not help, because you would still call setInterval over and over again after the timer variable is updated. Of course, you could use setTimeout instead of setInterval, but there are 2 other things that can be done with useEffect to pass an empty array as a dependency or use a cleanup function.

If you pass an empty array as a dependency, it will tell React that this effect doesn’t depend on any value, so it will never run again.

Another thing you can do is to use a cleanup function, which is similar to componentWillUnmount from the class component. Everything which is returned from function passed to useEffect will be called when the component is removed. Moreover, if a component is rendered multiple times like in that case, the last effect is clean before the next is executed. Here you could simply return clearInterval with the id of setInterval.

The ESlint plugin for React makes it a lot easier to take full advantage of hooks

React hooks best practices – summary

That’s it for this little React hooks tutorial. There is a lot more to cover about this topic, but I hope you found some useful tips for these two React hooks examples – useState and useEffect.

As you can see, hooks allow us to significantly simplify components in our application. However, when using them, there are some gotcha parts that need to be considered. If you follow these guidelines, your app will be less prone to bugs and also more understandable for other developers.

What do you want to achieve?

You can upload a file (optional)

Upload file

File should be .pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png format, max size 5 MB

0 % of

or contact us directly at [email protected]

This site is protected by reCAPTCHA and the Google
Privacy Policy and Terms of Service apply.


Thank you!

Your message has been sent. We’ll get back to you in 24 hours.

Back to page

We’ll get back to you in 24 hours

to get to know each other and address your needs as quick as possible.


We'll work together on possible scenarios

for the software development strategy in sync with your goals.


We’ll turn the strategy into an actionable plan

and provide you with experienced development teams to execute it.

Our work was featured in:

Tech Crunch
Business Insider

Aplikujesz do

The Software House

CopiedTekst skopiowany!

Nie zapomnij dodać klauzuli:

Kopiuj do schowka

Jakie będą kolejne kroki?


Rozmowa telefoniczna

Krótka rozmowa o twoim doświadczeniu,
umiejętnościach i oczekiwaniach.

Test task

Zadanie testowe

Praktyczne zadanie sprawdzające dokładnie
poziom twoich umiejętności.


Spotkanie w biurze

Rozmowa w biurze The Software House,
pozwalająca nam się lepiej poznać.

Response 200

Response 200

Ostateczna odpowiedź i propozycja
finansowa (w ciągu kilku dni od spotkania).


Webinar for CTOs: How to update your company’s legacy software

Sign up