← Back

React.js + Next.js · Module 3. Forms and Effects · Lesson 15 · Point 15

Multiple useEffect Hooks in React

React + TypeScript · GoIT Dev Notes

This lesson explains how one component can use several Effects, how each Effect responds to its own dependencies, and how rendering differs from external synchronization.

You will work with separate states, shared dependency arrays, document titles, console logging, derived values, StrictMode, and the exhaustive-dependencies rule.


REACT · 01

1. What Is useEffect?

The useEffect Hook lets a component synchronize with an external system such as a browser API, timer, network connection, or third-party widget.

Effects run after React commits the relevant changes to the DOM.

import { useEffect } from "react";

export default function App() {
  useEffect(function () {
    console.log("Component mounted!");
  }, []);

  return <h1>Hello React!</h1>;
}

Browser Result

localhost:5173

Hello React!

Component mounted!
The heading renders first; the Effect logs after the component is committed.

The empty dependency array means the Effect is associated with mounting. In development, StrictMode may run an additional setup and cleanup cycle to reveal bugs.

REACT · 02

2. Multiple useEffect Hooks

A component can contain several useEffect calls. Each Effect has its own setup function, optional cleanup, purpose, and dependency array.

import { useEffect } from "react";

export default function App() {
  useEffect(function () {
    console.log("First effect");
  }, []);

  useEffect(function () {
    console.log("Second effect");
  }, []);

  return <h1>Hello Nikita!</h1>;
}

Browser Result

localhost:5173

Hello Nikita!

First effectSecond effect
For the same commit, React processes these Effects in the order they are declared.

Although both run after the component mounts, they are separate Effects and should represent separate synchronization processes.

REACT · 03

3. Three Common Dependency Patterns

SyntaxWhen setup runs
useEffect(setup, [])After mounting
useEffect(setup, [count])After mounting and when count changes
useEffect(setup)After every committed render
import { useEffect, useState } from "react";

export default function App() {
  const [clicks, setClicks] = useState(0);

  useEffect(function () {
    console.log("Component mounted!");
  }, []);

  useEffect(function () {
    console.log("Clicks updated:", clicks);
  }, [clicks]);

  useEffect(function () {
    document.title = `You clicked ${clicks} times`;
  });

  return (
    <button onClick={function () { setClicks(clicks + 1); }}>
      You clicked {clicks} times
    </button>
  );
}

Browser Result

You clicked 1 times
Clicks updated: 1
After one click, the state-dependent Effect logs again and the no-array Effect updates the tab title.

The no-array form is valid, but it is broader than necessary here. If an Effect only uses clicks, [clicks] usually communicates the intended synchronization more precisely.

REACT · 04

4. Rendering vs. Re-rendering

Rendering means React calls a component function to calculate its JSX. Re-rendering means React calls it again, usually after state or props change.

export default function App() {
  console.log("Rendering!");

  return <h1>Hello!</h1>;
}

Browser Result

localhost:5173

Hello!

Rendering!
The function body runs while React calculates JSX; Effects run later, after a commit.
  1. React calls the component function.
  2. The component calculates JSX.
  3. React commits any necessary DOM changes.
  4. React runs the relevant Effects.

A render does not guarantee a visible DOM change. React may calculate the same output as before.

REACT · 05

5. Separate Effects for Separate States

import { useEffect, useState } from "react";

export default function App() {
  const [first, setFirst] = useState(0);
  const [second, setSecond] = useState(0);

  useEffect(function () {
    console.log("First updated:", first);
  }, [first]);

  useEffect(function () {
    console.log("Second updated:", second);
  }, [second]);

  return (
    <div>
      <button onClick={function () { setFirst(first + 1); }}>
        First: {first}
      </button>
      <button onClick={function () { setSecond(second + 1); }}>
        Second: {second}
      </button>
    </div>
  );
}

Browser Result

localhost:5173
First updated: 1
Changing first re-renders the component, but only the Effect whose dependency changed runs again.

REACT · 06

6. One Effect with Multiple Dependencies

useEffect(function () {
  console.log("First or second updated:", first + second);
}, [first, second]);

React compares every dependency with its previous value using Object.is. The Effect runs after mounting and again whenever either value changes.

ActionfirstsecondLogged total
Initial commit000
Click First101
Click Second112
Click First213

Use one Effect with several dependencies when one synchronization process genuinely depends on all of those values.

REACT · 07

7. Complete Example: Three Effects and Two Counters

import { useEffect, useState } from "react";

export default function App() {
  const [first, setFirst] = useState<number>(0);
  const [second, setSecond] = useState<number>(0);

  useEffect(function () {
    console.log("First updated:", first);
  }, [first]);

  useEffect(function () {
    console.log("Second updated:", second);
  }, [second]);

  useEffect(function () {
    console.log("Total:", first + second);
  }, [first, second]);

  function resetCounters() {
    setFirst(0);
    setSecond(0);
  }

  return (
    <div>
      <h1>Multiple useEffect Example</h1>
      <button onClick={function () { setFirst(first + 1); }}>
        First: {first}
      </button>
      <button onClick={function () { setSecond(second + 1); }}>
        Second: {second}
      </button>
      <p>Total: {first + second}</p>
      <button onClick={resetCounters}>Reset counters</button>
    </div>
  );
}

Browser Result

localhost:5173

Multiple useEffect Example

Current total3
First updated: 2Total: 3
After the First counter changes, its focused Effect and the shared total Effect run again.

The total displayed in JSX is derived directly during rendering. The shared Effect exists only to demonstrate synchronization when either counter changes.

REACT · 08

8. Always Specify Correct Dependencies

An Effect should declare every reactive value it reads. Reactive values include props and values declared inside the component, including state.

Incorrect

useEffect(function () {
  console.log(clicks);
}, []); // Missing clicks

The Effect reads clicks but promises never to synchronize again. The React Hooks ESLint rule should report the missing dependency.

Correct

useEffect(function () {
  console.log(clicks);
}, [clicks]);

Do not remove dependencies merely to suppress repeated execution. If an Effect runs too often, reconsider whether the Effect is needed, split its responsibilities, or stabilize the values involved.

REACT · 09

9. Why Separate Effects?

Separate Effects are useful when a component synchronizes with different external systems.

useEffect(function () {
  document.title = `Clicks: ${clicks}`;
}, [clicks]);

useEffect(function () {
  console.log("User changed:", username);
}, [username]);

The first Effect synchronizes the browser title. The second performs separate logging. Their purposes and dependencies are different.

Do Not Use an Effect for Ordinary Calculations

const total = first + second;

A total derived from current state can be calculated during rendering. It does not need another state variable or Effect because no external system is involved.

REACT · 10

10. Important Rules

  • A component can use multiple useEffect Hooks.
  • Each Effect has its own setup, optional cleanup, and dependency list.
  • Effects run after React commits changes.
  • An empty array associates an Effect with mounting and unmounting.
  • A dependency list reruns the Effect when one of its values changes.
  • Omitting the dependency array runs the Effect after every committed render.
  • One Effect can depend on several reactive values.
  • Declare every reactive dependency used by the Effect.
  • Separate Effects that synchronize with different external systems.
  • Calculate ordinary derived values during rendering.
  • Expect additional development checks under StrictMode.

Main idea: use several Effects when a component has several independent synchronization processes. Give each one the dependencies that describe exactly when it must reconnect or update.

← Back↑ Back to the top