2

I saw in the ReactJS docs that the dependency array in useEffect(fn, []) is optional, and not supplying it should be the same as supplying an empty array.

However, if I have the code as on: https://codesandbox.io/s/trusting-sunset-h6ip9?file=/src/Count.js

  useEffect(() => {

    console.log("SETTING INTERVAL");

    setInterval(() => {
      console.log("NOW", Date.now() / 1000);
      setDuration(Date.now() - startTime);
    }, 1000);

  }, []);

With the [] above, everything runs as expected. However, if I remove it and run again, as can be seen on: https://codesandbox.io/s/dreamy-platform-l93bv?file=/src/Count.js

We can see in the Developer's console or Codesandbox.io's console that the line "SETTING INTERVAL" is continuously being printed.

Supposedly, I thought having the empty array and not having in should make no difference, but in this case we need to put it in? What is the reason?

Stefanie Gauss
  • 425
  • 3
  • 9
  • When you don't supply second argument effect will run on each render. – Nikita Chayka Feb 26 '21 at 12:01
  • @NikitaChayka so on that page https://reactjs.org/docs/hooks-overview.html the example where it doesn't supply an empty array, it is meant to have it run every single time? If it is every single time, why use `useEffect(fn)` at all? Why not directly do what you want to do in `fn`? – Stefanie Gauss Feb 26 '21 at 12:14
  • because useEffect is called AFTER rendering, not during rendering – Nikita Chayka Feb 26 '21 at 12:17
  • @NikitaChayka so in some situation, it is needed to be after the rendering "When you call useEffect, you’re telling React to run your “effect” function after flushing changes to the DOM" (in the docs)... but in some situations, such as setting the document's title, it doesn't have to be "after". – Stefanie Gauss Feb 26 '21 at 12:28
  • Correct, and for that situation, you don't need useEffect, do you? :) – Nikita Chayka Feb 26 '21 at 12:29

3 Answers3

3

Very simply put, the array you provide is telling useEffect that it should run when the values inside the array changes. Since the value is static it will only run once. If you remove the array it will run on every render. You can also put a variable inside the array to tell useEffect to update whenever the variable changes.

Fantastisk
  • 488
  • 4
  • 11
  • so on that page https://reactjs.org/docs/hooks-overview.html the example where it doesn't supply an empty array, it is meant to have it run every single time? If it is every single time, why use `useEffect(fn)` at all? Why not directly do what you want to do in `fn`? – Stefanie Gauss Feb 26 '21 at 12:10
  • Yes it will run every time the state changes. So every time the button is clicked useEffect will update. UseEffect is good for monitoring variables and triggering functions once these changes. It is actually almost the same as using componentDidMount, componentDidUpdate, and componentWillUnmount. In most cases using UseEffect will be a bit cleaner and end up in smaller components. – Fantastisk Feb 26 '21 at 12:17
  • Also I think this subject deserves a bit more explanation. If I might suggest you to take a look here: https://wattenberger.com/blog/react-hooks This is by FAR the best explanation i have ever seen on using hooks. Especially if you are used to componentDidMount etc. – Fantastisk Feb 26 '21 at 12:40
  • When saying it runs on every render, can you explain precisely whether it runs 'before' or 'after' every render ? – Abdullah Sep 01 '22 at 17:03
1

There is a major and quite obvious difference between an empty array and an 'no deps'.

When you use an empty array, you are actually using componentDidMount in class components. But if you do not leave the same empty array, you will see that your counter does not work well.

If you do not want to use an empty array, you must clean up your useEffect.

See docs about "Effects Without Cleanup"

The reason the function does not work properly is that every time your component is updated, the counter also runs very fast. But with a simple clean up command this problem can be solved.

See docs about "Effects with Cleanup"

You can see an example for your hooks bellow:

  useEffect(() => {
    console.log("SETTING INTERVAL");
    setInterval(() => {
      console.log("NOW", Date.now() / 1000);
      setDuration(Date.now() - startTime);
      return function cleanup() {
         return 0;
         // Also you can use 'clearInterval' here or anything else to stop rendering more
      };
    }, 1000);
  });
qafoori
  • 781
  • 8
  • 13
  • so on that page https://reactjs.org/docs/hooks-overview.html the example where it doesn't supply an empty array, it is meant to have it run every single time? If it is every single time, why use `useEffect(fn)` at all? Why not directly do what you want to do in `fn`? – Stefanie Gauss Feb 26 '21 at 12:10
  • This is because sometimes when you are not using `useEffect`, you may get an error when your component is not yet fully built. Here you are only using `console.log`. But if you want to use `Refs` or `DOM`, you will definitely get an error. In fact, `useEffect` allows you to execute some commands after the component is fully loaded. – qafoori Feb 26 '21 at 12:15
-1

you need use like this:

useEffect(() => {
   const interval = setInterval(() => {
      console.log("NOW", Date.now() / 1000);
      setDuration(Date.now() - startTime);
    }, 1000);
   return ()=> clearInterval(interval)
  }, []);
Mohammadtz
  • 92
  • 1
  • 5