Content
- Introduction
- What arguments are passed to useEffect hook?
- First argument to useEffect
- Return value of effect
- Second argument to useEffect
- Passing a function as a dependency
- References
This is the third post of my react hooks series. If you haven't looked at the first two, follow the links below to look at them.
Introduction to useEffect hook.
A hook is a function which enables you use state and other react features without writing ES6 classes.
useEffect
hook is part of the react hooks API. If you are familiar with react life cycles, useEffect
hook is equivalent to life cycle methods componentDidMount
, componentDidUpdate
and componentWillUnmount
combined. In fact, according to the React documentation on Hooks, useEffect
hook was developed to address some of the challenges posed by life cycle methods of ES6 class components. Since this post is about what effect hook is and how it is used, i won't go into why it was developed. You can look at it Here.
In React functional components, we perform side effects
such as fetching data from an API or manually updating the DOM inside the useEffect
hook.
What arguments are passed to useEffect hooks?
useEffect
is a function which takes two arguments. The first argument passed to useEffect
is a function called effect
(You can guess why this hook is named useEffect
) and the second argument (which is optional) is an array of dependencies. Below is an illustration of how it is used.
import React, { useEffect } from "react";
import { render } from "react-dom";
const App = props => {
useEffect(() => {
console.log("Effect has been called");
}); //Second argument to useEffect has been omitted
return <h1> Hello world! </h1>;
};
const root = document.getElementById("root");
render(<App />, root);
First argument to useEffect
The first argument, called effect
, is a function which either returns a function (called cleanup
) or undefined
. effect
is executed when the component is mounted (on first render) and whether it is executed in subsequent updates is determined by the array of dependencies passed as the second argument.
Return value of effect argument
From the Previous section , we said the first argument to useEffect
is a function called effect
. effect
takes no parameters and it MUST return either a function or undefined. If it returns a function, then the function returned is called cleanup
. cleanup
is executed before calling effect
(to clean up effects from previous render). If you are curious about why and when cleanup is necessary, look at an explanation in the React documentation. Since effect
returns either a function or undefined, it is not uncommon to see effects
without cleanup
.
Second argument to useEffect
The second argument to useEffect
is an array of dependencies . If you want to control when effect
is to be executed after mounting the component, then pass an array of dependencies as the second argument. dependencies
are values defined outside useEffect
but are being used inside useEffect
like:
function App(){
const[state, setState] = useState(0);
// state is defined here
useEffect(() => {
console.log(state);
//value of state is used here therefore must be passed as a dependency
}, [state])
}
React compares the current value of dependency and the value on previous render. If they are not the same, effect
is invoked.
This argument is optional. If you omit it, effect
will be executed after every render. If you want effect
to be executed only on first render, you can pass an empty array.
useEffect(() => {
console.log("Effect has been called");
}, []) // Empty array as dependency, useEffect is invoked once
Dependencies can be state or props. It should be noted that any value defined outside useEffect
but inside the component, has to be passed as a dependency if you are to use it inside useEffect
. This is illustrated below.
function App(props) {
const [count, setCount] = React.useState(1);
// count and setCount are defined inside component(App) but outside useEffect
useEffect(() => {
//count is being used inside useEffect. Therefore must be passed as dependency.
console.log(count);
}, [count])
}
Passing a function as a dependency
You might be wondering if you define a function outside useEffect
and invoke it inside effect
, do you need to pass it as a dependency?
For exampe:
function App(props){
const [data, setData] = useState(null);
const fetchData = () => {
//fetch some data
}
useEffect(() => {
fetchData(); //Invoked inside useEffect
}, [fetchData])
}
It is not recommended to define a function outside and invoke it inside effect
. Above case leads to fetchData
being invoked on every render because the dependency passed is a function and functions are objects. React will compare fetchData
for previous and current render and the two will not be the same hence triggering a call to effect
.
According to React documentation on useEffect hook,
It’s difficult to remember which props or state are used by functions outside of the effect. This is why usually you’ll want to declare functions needed by an effect inside of it. Then it’s easy to see what values from the component scope that effect depends on:
You can also move the function inside the effect so that it doesn’t need to be in its dependency list.
Thank you for reading this far. This is a brief introduction to useEffect
. There are lots of things about useEffect
hook i have not touched in this article. It takes some time getting used to it. If you want to deeply understand useEffect
, look at the references below. If you find this article useful, share it on Twitter. Someone could find it useful too. If you find anything technically inaccurate please feel free to comment below.
Top comments (4)
such a nice article !!! Thank you for your work !!!
Thank you it's make me completely clear about section render every time when update DOM.
one of the nice, well explained and to the point article on useEffect... really.
Thanks a lot :)
Good article for lazy people like me.. I hope you will write similar explanations and usage for other important Hooks too.