Learn React Hooks in 2021

A hands-on guide to transition to React hooks. Let’s get you hooked!

Are you still using class-based React components? Did you never have the chance to use React Hooks? You are not alone, although React hooks have been there for a while, some developers haven’t got around to using them yet.

In this article, we will show you how class-based components translate to React hooks. We will also go into detail for each hook and explain its capabilities using code samples and exercises. At the end of this article, you should become a master of the basic React hooks.

Are you ready to dive into hooks? Let’s go!

React component

Make sure to follow along with the examples and create them into a demo react app. The more hands-on experience the more you’ll get used to the syntax and concepts.

React class-based component

Let’s first take a look at a simple class-based component and see how to translate this to using hooks.

This is a typical class-based component. Let’s take a look at the building blocks for a functional component. Instead of having a class, we will have one function which will handle everything. Instead of having a render method separately, this function will now be your new render method.

Functional components template

That’s how easy it is, it’s similar to a render method that receives the props as a parameter. An often-used way to make your props more readable is to destructure them using the spread operator, as follows.

This way, we can clearly see which props we expect. If we do this in combination with TypeScript, this could make the React PropTypes redundant.

React state hooks

Since we are working with functions, we don’t really have this available as it used to be in class-based components. To solve this issue, React came up with hooks . These are pieces of code that can be used within your functional component to access the previously available concepts.

For the case of the state, we can use React’s useState hook. If you are interested, here’s the official React documentation on useState. First, let’s define the useState variable as defined in the documentation.

You will immediately notice the useState syntax looks quite strange. It is because we are immediately destructuring it. The useState hook returns an array containing two items. The first item is the value of the state variable. The second item is the setter method for the state variable. Say, we want to update the headingText value in the state, then we can use the variable returned in the second item for this. Here’s an example:

How would this look like with multiple state variables? For each of the state variables, we’ll need to use the useStatehook.

Also important to note, is that we always passed a string to the useState method. UseState will use this as the default value for the state variable, so this does not have to be a string, it could be a boolean, an object, or anything you’d like.

Exercise: useState — Implementing a click counter with hooks

If we look back at the previous example, we see how the state can be used, but the state is not particularly useful in this example. Let’s complete an exercise on useState together!

Let’s create a click counter with the useState hook in a functional component. The component should render a button. Every time the button is pressed, a paragraph should show the number of clicks on the button. You’ll have to keep the number of clicks in the state. Use the useState hook.

Also, implement a prop that will set the initial amount of clicks to a specified value. If 20 is given to the component, then the component should show 20 clicks from the beginning.

Once ready, scroll down below the image to find the solution.

Photo by The Average Tech Guy on Unsplash

Here’s the solution:

Did you encounter any difficulties? Let us know in the comments!

React lifecycle and useEffect

We now know how to create functional components, and use the useState hook. But what about lifecycle events?

React componentDidUpdate

Using the class-based componentDidUpdate function, we could listen to changes in props of a component. How would we do this with hooks?

That’s where the useEffect hook comes in. Whenever the value of a dependency has changed, it will trigger a given function. This hook does not return an array, instead, it allows you to run specific code when specific variables change during execution.

The useEffect expects two parameters. The first one being the function to be run, the second parameter being the dependency list. The dependency list is a list of variables. Whenever any of these variables are changed, the given function in the first parameter will be run.

React ComponentDidMount

Remember in class-based React, we also had a function componentDidMount ? Whenever the component is mounted on the page, the function would run. With useEffect we need to provide a dependency list, so it is not suitable for replacing componentDidMount right? Not exactly! It has a trick up its sleeves.

If we pass an empty list as a dependency list, the function given as the first parameter will be run in a similar way as componentDidMount . Let’s try it out and extend our previous click-counter example! Note that the empty list is mandatory for this behavior. A common mistake from developers is to forget to define the list at all. If undefined is given instead of [] , then the useEffect will not behave like componentDidMount !

React Context hook

The third and final hook classified as basic by the React team is the context hook. This hook allows you to pass data from the top of your application to all recursive children. This is often useful for creating providers, such as theme providers, so every component has access to the app’s theme style.

Do note, while we can pass down the context using the useContext hook, we cannot update it! If this is needed for your application, then you will probably have to look at a state manager such as Redux instead.

We will not go into too many details on this hook, but here is an example usage from the React documentation, along with annotations:

React useMemo hook: performance optimization

React provides us the useMemo hook to improve the performance of applications. The useMemo hook accepts two arguments, similar to useEffect : a function to execute, and a dependency list. One difference with useEffect is that this hook will return the value of the function, so its value can be used within the functional component.

UseMemo will cache the value of the method, as long as the dependency list does not change. This means the method to calculate the value will not be run unless one of the values in the dependency list changes.

This is especially useful when working with variables by reference. If an array is defined in your functional component, the reference will keep changing on re-render. If this array is then passed on to children components, these will keep on re-rendering, when this is in fact not needed.

When using useMemo , we can avoid this behavior by caching the array and its reference until one of its dependencies for calculating its value changes. Let’s take a look at an example.

For pass by reference variables, useMemo can be useful to avoid re-rendering sub-components on every render of our main component. This is because we are caching the variable reference instead of redefining it on every render. Is this the only reason to use useMemo ? Not exactly. It can be very useful for large processing.

Take a look at my article Should You UseMemo in React? A Benchmarked Analysis to find out exactly when you should be using useMemo in your React applications.

View more about the useMemo hook at the official documentation page.

React useCallback hook

The useCallback hook is similar to the useMemo hook, but instead of memoizing values of variables, it memoizes functions. It works on the same concept, in order to avoid the reference of the function changing on every render, cache the function until one of its dependencies change.

This avoids unnecessary re-renders from children components that receive this function as a prop.

React hooks list

The above-explained hooks are some of the more important hooks to use in React. React does have more hooks, here’s a list of hooks per type, as defined by React in the official documentation.

Basic hooks

  • useState for managing the state of a component
  • useEffect for lifecycle events of a component and triggering specific functions if specific dependencies change
  • useContext in order to pass down a context to all sub-components

Advanced hooks

  • useMemo for memoizing variable values
  • useCallback for memoizing functions
  • useReducer for creating and using custom reducers
  • useRef for defining refs to components in the DOM
  • useImperativeHandle can be used for customizing the value returned by useRef
  • useLayoutEffect similar to useEffect but only fires after all DOM updates
  • useDebugValue used for displaying debug data when developing custom hooks

Third-Party hooks

Anybody can create additional hooks for React. Redux, a popular React state manager has created the useSelector hook in order to retrieve Redux state data from within the functional components. If you have Redux already setup, retrieving the Redux data using this hook is a piece of cake.

Hooks Cheat Sheet

  • useState : const [value, setter] = setState(defaultValue);
  • useEffect : useEffect(myFunction, dependencyArray);
  • useEffect : usage for didMount useEffect(myFunction, []);
  • useContext : React.createContext(object) and useContext(MyContext);
  • useMemo : const myValue = useMemo(calculateFunction, dependencyList);
  • useCallback : const myFunction = useMemo(callbackFunction, dependencyList);
  • useSelector : const result = useSelector(state => state.item);

Summary

A current trend in React development is to move to using hooks. Hooks and class-based components are interoperable and compatible! You could have newer components made as functional components while keeping the older components class-based.

Do not worry, however, React is not going to remove class-based components any time soon.

There are no plans to remove classes from React - we all need to keep shipping products and can't afford rewrites. - React Team

What’s next?

Practice, and practice! The more you get hands-on experience with hooks, the faster you’ll get used to them. Create some pet-projects using React hooks. It’s fun, and you’ll get a nice project out of it!

Stay tuned for the next article regarding React hooks, in which we will create our own custom React hooks!

Extra Study Resources

Kevin Van Ryckegem

Kevin Van Ryckegem