avatarJoanna Marie

Summarize

React Interview: Why those useEffect hooks are not working as expected?

Photo by Caspar Camille Rubin on Unsplash

Interview: Why those useEffect hooks are not working as expected?

import { useState, useEffect } from "react";

export default function App() {

  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setCount1(count1 => count1 + 1);
    }, 1000);

    return () => clearInterval(intervalId);
  });

  useEffect(() => {
    const intervalId = setInterval(() => {
      setCount2(count2 => count2 + 1);
    }, 3000);

    return () => clearInterval(intervalId);
  });

  return (
    <div className="App">
      <p>Counter 1: {count1}</p>
      <p>Counter 2: {count2}</p>
    </div>
  );
}

Expected result

In this functional component I’m creating two counters, each one increments at different intervals.

  • It initializes two more state variables count1 and count2. Both are initially set to 0. These variables will store the values of the two counters.
  • It uses two useEffect hooks. They set up intervals to update the counters at specified intervals.
  • The first useEffect sets up an interval for count1 to increment every 1 second (1000 milliseconds). It also returns a cleanup function that clears the interval when this useEffect is unmounted or when the component is re-rendered.
  • The second useEffect does the same for count2, but it increments it every 3 seconds (3000 milliseconds).
  • The return statement defines the JSX that will be rendered on the web page. It displays the current values of count1 and count2.

So expected result is to see something like this:

However, it’s working in this way:

Why it is not working?

The issue with the second counter not updating as expected is due to the lack of specifying a dependency array in the useEffect hooks.

  • During the initial render, the component is displayed with both count1 and count2 set to 0.
  • After the initial render, the useEffect hooks are executed.
  • The first counter (count1) has a shorter interval and updates every 1 second, calling setCount1. This causes the component to re-render with the new value of count1 (which is 1) after 1 second.
  • As a result of the re-render, the cleanup functions of both useEffect hooks are called, clearing both intervals.
  • In the next render, count1 has a value of 1, but count2 is still at 0.
  • The useEffect hooks run again.
  • The first counter once again calls setCount1 after 1 second to increment count1. This re-renders the component with count1 value of 2.
  • However, the cleanup functions are called again for both useEffect hooks, preventing the second counter from updating count2.

Conclusion

In React’s useEffect hook, specifying a dependency array is not always required, but it can be crucial for controlling when the effect runs and ensuring that your component behaves as expected or if it is running infinite loop.

If you enjoyed this article, consider trying out the AI service I recommend. It provides the same performance and functions to ChatGPT Plus(GPT-4) but more cost-effective, at just $6/month (Special offer for $1/month). Click here to try ZAI.chat.

React
React Hook
JavaScript
Interview
Front End Development
Recommended from ReadMedium