DEV Community

Cover image for Understand the second argument of useEffect (Bite-size article)
koshirok096
koshirok096

Posted on • Updated on

Understand the second argument of useEffect (Bite-size article)

Intro

useEffect is one of the most frequently used Hooks in React, but I found it's difficult to understand the all of its concepts. To understand useEffect little by little, I will dig deeper into the second argument on useEffect.

It may sound a little strange that this article focuses only on the second arugment. However, it was the point at which I stumbled, and I hope it will help others like me!

Image description

useEffect Basics

useEffect is one of React Hooks that to perform side effects in your react project.

useEffect(<function>, <dependency>)
Enter fullscreen mode Exit fullscreen mode

The first argument is literally function which you want to use, and the second argument is a dependency array, which is used to specify the conditions under which useEffect is triggered.

Let's take an in-depth look at the second argument.

Concept of Second Argument

I belive it is difficult to understand from only a text explanation, so let's look at the actual code example.


import { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
    setCount((count) => count + 1);
  }, 1000);

  return () => clearTimeout(timer)
  }, []); // here is the place for 2nd argument

  return (
    <div>
      <p>I'm counting. Now total count is: {count}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

This is a simple code that counts every second. In the code example above, the second argument is []. But there are several patterns.

1. With Empty Array

useEffect(() => {
  //Function with empty array
}, []);
Enter fullscreen mode Exit fullscreen mode

With this way, useEffect will only execute at the first time rendered, and will not be reexecuted thereafter. This means that side effects will no longer be cleaned up when components are unmounted.

So if you run this code on your environment, then the count will be done only once. Please check it out by yourself.

2. No Dependency

useEffect(() => {
  //Only function. No Dependency
});
Enter fullscreen mode Exit fullscreen mode

Let's look at the second pattern.

First, keep in mind that this second argument is always optional. So you can also pass nothing to the second argument like above. If there is no second argument, it takes a function that is executed for everytime your project rendered.


import { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
    setCount((count) => count + 1);
  }, 1000);

  return () => clearTimeout(timer)
  }); // no dependency

  return (
    <div>
      <p>I'm counting. Now total count is: {count}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Let's change your codes as above, and run it on your environment to compare with previous one. useEffect is executed at the first rendering, and at every subsequent rendering. That is, the side effects set within useEffect will continue until the component is unmounted.

In the previous example, the count was only done once, but this pattern should continue to be counted.

3. Props or state

useEffect(() => {
  //put props or state in it
}, [something]);
Enter fullscreen mode Exit fullscreen mode

Here is third example (last one). You can pass props or state as the second argument.

With this way, useEffect is reexecuted only when the variable specified in the array is changed. This allows side effects to be executed only when a specific state or property changes. Here is the example code.


import React, { useState, useEffect } from 'react';

export function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
    console.log(count);
    return () => clearTimeout(timer);
  }, [count]); // here has count now

  return (
    <div>
      <p>I'm counting. Now total count is: {count}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this example, count is set in the second argument. This means useEffect works everytime count changes triggered.

Tip: Multiple variables

Also, the second argument may be an array containing multiple variables. If any variable in the specified array is changed, useEffect will be rerun.


import React, { useEffect } from 'react';

const SomeComponent = ({ propA, propB }) => {
  useEffect(() => {
    console.log('propA and propB are changed:', propA, propB);
  }, [propA, propB]);

  return (
    <div>
      <h2>SomeComponent</h2>
      <p>propA's value: {propA}</p>
      <p>propB's value: {propB}</p>
    </div>
  );
};

export default SomeComponent;

Enter fullscreen mode Exit fullscreen mode

Image description

Outro

It is difficult to understand many things at once, but if you can understand at least one thing a day, it can be a big step.

This article is more for my own understanding, but I hope it will help you.

Top comments (0)