React Hooks: what they are and how to use them

Photo by Zyanya BMO on Unsplash

I have been using React for a couple of months and I am loving it. In the process, I saw it’s almost better to use functions instead of class components.

Yet, functional components didn’t offer many functionalities back then. So you had to transform it into a class component to have access to state or lifecycle methods (duh).

Since React 16.8, the state and component lifecycles are available in functional components. And they are called React hooks. In this article, I’ll walk you through them.

From the React documentation, hooks are a solution to a problem. They make functional components have the same functionalities as a class component.

Class components are not always easy and can bring confusion. One example is the this keyword where you’ll have to always bind it to the class.

With React hooks, you won’t have these problems. Plus, your functional component will behave like a class component.

There are many React hooks. But the ones developers use the most (and that’s also true for me) are the useEffect and useState. Let’s look at each of them:

The effect hook will let you apply side-effects to a component. What is a side-effect? A side effect can be:

  • Fetching data after the component mounts
  • Changing the DOM content of a component

A component that doesn’t have side effects is a pure component.

useEffect comes as a replacement for the componentDidMount in a React class component.

To illustrate our example, let’s build a component fetches data after mounting. One will be a class component, the other will be the functional component. Using the componentdidMount lifecycle method, we’ll have the class component like this:

import React, {Component} from 'react';class App extends Component {componentDidMount(){
fetch('api/recipes')
...
}
... rest of the class component}

This App class component fetches the data after the component mounts.

Now, if we want to do the same for a functional component, we have to use the effect (we import it from ‘react’)

import React, {useEffect} from 'react';function App() {
useEffect(() => {
fetch('api/recipes')
})
... rest of the functional component}

useEffect takes an anonymous callback function. In that callback function, you can whatever you want. Your operation will happen after the component renders or updates.

This is very important (the render and update keywords). Because every time the component renders (or updates), useEffect fires. So if you want to fetch data after the component renders, useEffect is the way to go.

Yet, this can lead to an infinite rendering. When useEffect gets called, it often changes the app state (side effect). This will make the app rerender and useEffect fires again…

So to fetch data only once, you need to add a dependency array to useEffect like this:

import React, {useEffect} from 'react';function App() {
//we add an empty array as a second parameter to useEffect
useEffect(() => {
fetch('api/recipes')
},[])
... rest of the functional component}

This empty array as a second parameter will make useEffect run only once. Your app will work without rerendering.

useState is another hook that helps you set a state to your functional component. Functional component are like normal functions: they don’t hold a state by default. With useState, you can now have a state for your functional component like a class component. Here’s an example with a class component:

import React, {Component} from 'react';class App extends Component {
constructor(){
super();
this.state = {
user: 'user123',
}
componentDidMount(){
fetch('api/recipes')
...
}... rest of the class component

In this class component, you have access to the state by using this.state. But you can’t do the same for the functional component. Hence the useState hook. Let’s see it in action with a functional component

//we import useState from react (like useEffect)
import React, {useEffect, useState} from 'react';
function App() {//now we can use useState
const [user, setUser] = useState(‘user123’)
useEffect(() => {
fetch('api/recipes')
...
})
... rest of the functional component}

What does this syntax mean?

useState returns two things: the state and the function to change that state. We then use restructuring to “extract” those two elements we need. In our example, the state will set the default user to ‘user123’. And setUser as the function that updates the user’s state. So if we want to update the state, we can use:

setUser(‘newUser’)

This will change the state to the new user. Note that you can choose whatever name for your state and setting state function.

I am a full-stack developer with a passion for technology and learning new things. Founder of JavaScriptLearned.