Why is my useEffect Hook executed in an endless loop?

Did you already try the `useEffect` hook, maybe to fetch data on the first mount of your component? How did it work out for you?

I really liked my first experience with the useEffect Hook. Now it’s no longer necessary to refactor a functional component to a class component. At least not just because you need state or some lifecycle methods.

So there it is – our Hook that is going to load some Users from an API to display it in a UserList component:

  useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(result => setData(result.data));
});

Did you too realize that the hook, and – if available – the cleanup function we just wrote are executed endlessly? Just Add a console.log and see!

useEffect is Executed at each Render

Unlike componentDidMount, useEffect is not executed when the component finished mounting, but each time the component is rendered.

That means if you modify the components state inside useEffect, it will cause a re-render of the component, which again causes the execution of useEffect.

That’s not a great thing if you want to load data only once, right?

That’s why useEffect takes an array of dependencies as a second argument.

The Power of Dependencies

There are many use cases of useEffect so this is something critical to know.

Did you know you can pass an array of objects (dependencies) to useEffect? If you do, each time one of those objects change, React will execute this certain Hook.

But what if we only want the hook to execute when the component is mounted and rendered the first time?

In our example case we only want to execute useEffect once when it is rendered the first time. We already know, if we don’t pass an array of dependencies, the Hook will be executed in a loop. But what if our hook does not depend on any other object?

So we pass an empty array.

That’s it:

useEffect(() => {
// this is only executed once
}, [])

If we pass an empty array to useEffect, it’s only executed after the first render.

Wrapping Up

In some cases it makes sense that our Component calls useEffect at each render. But if you want to replace a class component’s componentDidMount with this method, keep in mind to pass either an empty array so you don’t end up with a component that endlessly renders itself.

Improve your React Skills!

Learn about React concepts, helpful libraries or get tips & tricks for deploying your app and many more topics.

I semi regularly post about React. Don't miss out on my future posts! Sign up below to get them delivered directly into your inbox!

Leave a Reply

Your email address will not be published. Required fields are marked *