React has a built-in hook called useEffect. Hooks are used in function components. The Class component comparison to useEffect are the methods componentDidMount, componentDidUpdate, and componentWillUnmount.
useEffect will run when the component renders, which might be more times than you think. I feel like I’ve had this come up a dozen times in the past few weeks, so it seems worthy of a quick blog post.
import React, { useEffect } from 'react';
function App() {
useEffect(() => {
// Run! Like go get some data from an API.
});
return (
<div>
{/* Do something with data. */}
</div>
);
}
In a totally isolated example like that, it’s likely the useEffect will run only once. But in a more complex app with props flying around and such, it’s certainly not guaranteed. The problem with that is that if you’re doing something like fetching data from an API, you might end up double-fetching which is inefficient and unnecessary.
The trick is that useEffect takes a second parameter.
The second param is an array of variables that the component will check to make sure changed before re-rendering. You could put whatever bits of props and state you want in here to check against.
Or, put nothing:
import React, { useEffect } from 'react';
function App() {
useEffect(() => {
// Run! Like go get some data from an API.
}, []);
return (
<div>
{/* Do something with data. */}
</div>
);
}
That will ensure the useEffect only runs once.
Note from the docs:
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders.
Or simply use eslint-plugin-react-hooks to be sure about your hooks and how you’re using them!
https://www.npmjs.com/package/eslint-plugin-react-hooks
That looks useful but I don’t think it solves the problem.
This is absolutely correct, but can be dangerous when misunderstood and misused/overused.
There’s an amazing (but long) explanation of all the ins and outs of useEffect written by Dan Abramov which really crystalized it for me.
https://overreacted.io/a-complete-guide-to-useeffect/
Two things, by design, React will render when props or state changes. Since
useEffectruns each and every time, you are bound to fall into an infinite loop if you change the state or props in it. Also, to getcomponentDidMount, you run some code then you pass an empty array as the second parameter touseEffect. To runcomponentWillUnmountjust once, you return a cleanup function fromuseEffectand pass an empty array as the second parameter too.I’ve been converting some of my codebases to Hooks, and it’s getting pretty fascinating. One thing with
useEffectis that it’s easy to mess it up – and I already did quite a number of times. But apart from that, it solves a lot of problems and as a bonus, it does it simply.The issue with this approach is that it will fire a warning if you depend on any props or state (due to the
react-hooks/exhaustive-depseslint rule).Better define a custom Hook in your codebase:
And import it and use it.