Beginner’s Guide to Using useState & useEffect React Hooks

Danielle Arquisola
The Startup
Published in
6 min readOct 27, 2020
Source: https://vignette.wikia.nocookie.net/spongebob/images/d/d8/Hooky_048.png/revision/latest?cb=20190906080723

You are a developer with previous experience using React, and you are comfortable using React class components. You’re so comfortable with class components to the point that switching to functional components sounds daunting. How are you going to set state? How can you access the react component lifecycle?

If this sounds like you, then this guide will help you begin transitioning your class components into functional ones. React hooks provide an ability to use state and lifecycle functions within functional components.

We will discuss two built in hooks: useState and useEffect.

useState

A key difference between class and functional components is the fact that class components have a state while functional components are stateless. The useState hook allows us to add local state to a functional component. This hook holds onto a state between re-renders.

Let’s start by comparing the different components.

Class component showing how to use this.setState

In the image above, we have a stateful component. As you’re already familiar with class components, let’s make this explanation brief. A constructor is made at the beginning of the component and it sets the initial state. “num” is the only value in this example, and it is initially set to the 0. To reset the state, this.setState is called within the setNum function. The onClick event within the button tag invokes setNum, allowing the state to update. Simple, right? But can it be this simple within a stateless component?

Below we have an example using the useState hook.

Functional component showing how to use useState

Now let’s break down what’s going on in this stateless component.

  1. Importing useState
    First things first. Make sure to import { useState } from “react”
  2. Declaring the state variable for the component
    To declare the state variable, a pair of values needs to be set equal to the useState method. The pair of values are the current state and a function that updates the current state. useState will always return this pair of values. In our example, num and setNumValue are set to useState. We have now declared a new state variable called num and the function that updates it is setNum.
  3. Initializing the state by passing in the initial value in the useState method
    The state of the variable is initialized by passing an initial value in the useState method. For our example, we chose to pass 0 in useState. Our state variable num is now initially set to 0.
  4. No use of “this” or “this.state”
    Stateless components do not use the “this” keyword. By using the useState hook, we can call the state directly with the variable we have set for it.

Note: When using useState, every instance of state should have its own hook.

useEffect

The useEffect hook lets us implement lifecycle methods to tell the component to perform an “effect” after it is rendered. The different types of effects are limitless such as changing the background image or document title, adding animations or music, data fetching, and subscriptions.

As previously mentioned , the useEffect hook allows us to use React’s lifecycle methods within a stateless component. It is important to note that the useEffect hook is not a perfect copy of a replacement for all of the lifecycle methods. As a beginner, we’ll look into mirroring the effect componentDidMount and componentDidUpdate.

Let’s first take a look at any example of using these lifecycle methods in a stateful component.

Class component demonstrating the use of lifecycle methods

Again, let’s keep the explanation short and sweet when reviewing the class component. If you need to brush up on react lifecycles, check out: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

componentDidMount will be immediately invoked after a component is mounted. In our example, when ClassComp is rendered, the string “The component was successfully mounted!” will appear in the terminal alone without a color.

While viewing the page, let’s say you chose the button that says “RED.” componentDidUpdate is then invoked. The terminal will now print out “The component was updated!” followed by “RED.” If you decide to choose the blue button, componentDidUpdate will be invoked again, as it would be each time you chose a different button. componentDidUpdate is executed any time the component has re-rendered.

How can we do this in a functional component?

Functional component showing an example of using useEffect

Let’s discuss what is happening here.

1. Importing useEffect
Again, always make sure you are importing at the top!

2. useEffect can be called more than once.
In the class component, both componentDidMount and componentDidUpdate were declared. In our example, useEffect was called two separate times, with different arguments passed inside.

useEffect first accepts a function as a parameter. The second parameter in useEffect is an array that contains a list of state variables that rendering/re-rendering should watch out for. If one of the items in the array changes, then the function that was written alongside it will be invoked.

3. Copying “componentDidMount”
Within class components, componentDidMount will execute only after the first render. Remember how we were just talking about the second argument? Let’s utilize that to make sure that useEffect will only be invoked after the initial render.

useEffect(() => {
// perform a task
}, []);

By passing an empty array in the second argument, useEffect will only be executed after the first render. It would not run again because the value of the array will not change.

In our example, the console will read “This component was also mounted!” after the initial render. Because there is an empty array in the second argument, this string will no longer be logged to the console during if the component is rendered again.

4. Copying “componentDidUpdate”
When we first used the useEffect hook to mimic componentDidMount, we passed an empty array as the second argument. To mimic componentDidUpdate, we will add the dependency in an array as the second argument.

useEffect(() => {
console.log(value);
}, [value]);

Visually, one big difference between this example and the componentDidMount clone, is that the second argument is no longer an empty array. Do you see that “value” that’s inside the array? Anytime that value is true, the function in the first argument will be invoked. The example above is a console.log, but you can implement any function you want.

In our large code block example, any time “color” is true, the second useEffect hook will run. “color” will always be true in our example, due to the fact that it will either be red or blue. Anytime the color is switched, we will see “The color changed! Just like componentDidUpdate” printed in our terminal.

Reminder: React first updates the DOM, and then it calls any function that is passed into useEffect()

Next Steps

Now you’ve been introduced to two of React’s built-in hooks! What’s next?

1. Look into other built-in hooks! Here’s a good resource that acts a sandbox for you to test out the built-in hooks: https://react-hooks-cheatsheet.com/

2. Try to change your current class components into functional ones.

3. Create your own custom hooks!

--

--