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.
This is an anti-pattern to look at useEffect with an empty array as ComponentDidMount. If someone tries to stick props inside this useEffect, intending that it only fires on mount, they are following an anti-pattern described by the React team. Even if you only want someone to render on mount it should always have its dependancies in the array as that is what React expects of it.
Well you’re right, it’s not specifically a replacement for componentDidMount. But if I want something to only fire when the component is mounted, using useEffect with an empty array is currently the only way to achieve this, or did I get that wrong? In all other cases, I agree – if possible, we should provide dependencies. But what if there aren’t any?
if we didn’t add all dependencies, they give some error like below,
“React Hook useEffect has missing dependencies: ‘XXXXX’, ‘XXXXX’, and ‘XXXX’. Either include them or remove the dependency array”
It’s the only way I’ve found to stop the endless loop.
I’m glad I could help 🙂
this code :
useEffect(() => {
// this is only executed once
}, [])
saved my ass.
Thanks man
why I can’t find this piece of advice in React documentation,
that’s is really frustrating, that React community still keeps documentation as simple as possible for newbie’s only.
Thank a lot, Andreas.
ok, found it here:
https://reactjs.org/docs/faq-ajax.html
But, anyway you should be an ultra-attentive person being able to notice this empty array in the end of call
It shows an empty array in console of I use [] in useeffect else it re renders