I am trying to understand the useEffect
hook in-depth.
I would like to know when to use which method and why?
1.useEffect with no second paraments
useEffect(()=>{})
2.useEffect with second paraments as []
useEffect(()=>{},[])
3.useEffect with some arguments passed in the second parameter
useEffect(()=>{},[arg])
useEffect enables you to run something whenever the the component is rendered or when a state changes. Having that inside of a function that is called on click makes it useless. useEffect should call other functions, but should never be called from within a function.
What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we'll refer to it as our “effect”), and call it later after performing the DOM updates.
The motivation behind the introduction of useEffect Hook is to eliminate the side-effects of using class-based components. For example, tasks like updating the DOM, fetching data from API end-points, setting up subscriptions or timers, etc can be lead to unwarranted side-effects.
You can have multiple useEffects in your code and this is completely fine! As hooks docs say, you should separate concerns. Multiple hooks rule also applies to useState - you can have multiple useState in one component to separate different part of the state, you don't have to build one complicated state object.
useEffect(callback);
// Example
useEffect(() => {
console.log("executed after render phase");
return () => {
console.log("cleanup function after render");
};
});
const Component = () => {
callback()
return <></>;
};
Note: There is still a difference, in execution time (see the next note). Check this sandbox logs.
useEffect(callback,[]);
// Example
useEffect(() => {
const fetchUsers = async () => {
const users = await fetch();
setUsers(users);
};
fetchUsers();
console.log("called on component's mount");
return () => {
console.log("called on component's unmount");
};
}, []);
Gotchas:
Remember, there is a first render and then a mount.
Roughly saying, most of bugs regarding
useEffect
is not knowing how closures works and not paying attention to linting warnings.
Make sure the array includes all values from the component scope that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders - note in React docs.
useEffect(callback,[arg]);
// Example
useEffect(() => {
console.log({ users });
return () => {
console.log("user value is changing");
};
}, [users]);
arg
value.[arg1,arg2,arg3...]
arg
value change.Gotchas:
arg
.i.e compares the value of
arg
from the previous render and the current one,prevArg === arg ? doNothing() : callback()
.
Because in Javascript {} === {} || [] === []
is a falsy statement, if arg
(users
in our example) is an object, the callback will run on every render.
Runs on mount too, since the first comparison always falsy
useEffect
callbacks fired after browser's re-paint.useEffect
callbacks executed in declaration order (like all hooks), check the example.useEffect
should have a SINGLE responsibility.useRef
, in the cleanup function, copy the value to callback's scope beforehand.const timeoutIdRef = useRef();
useEffect(() => {
const timeoutId = timeoutIdRef.current;
return () => {
/*
Using timeoutIdRef.current directly here is not safe
since you can't guarantee the ref to exists in this point
(especially when the component unmounts)
*/
// Should get a lint warning here
clearTimeout(timeoutIdRef.current); // BAD
// Closure on timeoutId value
clearTimeout(timeoutId); // GOOD
};
}, [arg]);
ref.current
as useEffect
's dependency when ref points to a DOM element?useEffect
ONCE, on mount or on first render, those are the common patterns.const isMounted = useRef(false);
useEffect(() => {
if (isMounted.current) {
// first mount
} else {
isMounted.current = true;
}
}, [arg]);
Keep reading:
return
statement of useEffect
callbackuseEffect
by Dan AbramovuseEffect
APIIf you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
1.useEffect with no second paraments : This is used when we want something to happen either when the component just mounted, or if it has been updated. Conceptually, we want it to happen after every render.
2.useEffect with second paraments as [] : This is used when we want something to happen at the time of mounting of the component, if only executes once at the time of mounting.It is closer to the familiar componentDidMount and componentWillUnmount.
3.useEffect with some arguments passed in the second parameter:This is used when we want something to happen at the time when the pramter passed eg. args have changed in your case.
For more info. check here: https://reactjs.org/docs/hooks-effect.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With