useEffect() — what, when and how. useEffect() is a react hook which you…
By: Abhishek Ranjan
Tags: Web Development, React, React Hook, Useeffect, Reactjs

useEffect React Hook

Syntax :- useEffect( ()=>{} , [dependencies] ). It takes two arguments separated with a comma, first — a function that you want to execute whenever useEffect runs. In the above case we shall run setTimeout inside useEffect. Second — an array of dependencies.

useEffect runs after the rendering/re-rendering of the component but only if any of the dependencies is changed. Remember it runs after the component is rendered(or mounted) not before, not along with but only after the component is rendered. Let me show you this with an example.

import React, { useEffect } from "react"; export const Test = () => { useEffect(() => {

console.log("Effect");

}, []); console.log(“rendered”); return <>{console.log("UI rendered")}</>;

The console output will be in the order : rendered , UI rendered , Effect

The 2nd argument (array of dependencies)

We will see three cases to understand use of dependencies in useEffect hook

Case I. Array with few dependencies :-

Here the useEffect has two dependencies — value1 and value2.

The “effect” will log in the console —

For the very first time when the component is rendered (because for the very first time value of dependencies value1 and value2 seem to be changed to react). Again if any of the states of value1 or value2 will be changed but not if the state of value3 is changed.

CASE II. Array with no dependencies (empty array).

Here useEffect has the 2nd argument of empty array.

The “effect” will be logged only when the component is rendered very first time. It will not run if “the state of value” is changed (the component will re-render but still the useEffect won’t run).

Now, the question comes why did the effect run only once. Here is answer to your question —

For the very first time useEffect runs after component evaluation because you had no dependencies before. But once it ran for the very first time, now it has no dependencies but also they didn’t change compared to the first execution cycle.

Case III. Without the 2nd argument [ useEffect( ()=> {} ) ]

Can we have useEffect without the 2nd argument ? Yes, and here is our third and last case. You will use this case very rarely. In this case useEffect runs after every render and re — render of the component.

The “effect” text will be logged every time after component renders or re-renders. Here comes one more interesting question — what will be the difference if instead of

useEffect(() => {

console.log(“effect”);

});

We directly write —

console.log(“effect”);

The difference is that the first one will run ( “effect” will be logged ) after the component is evaluated or re — evaluated while the second one will run (“effect” will be logged) during / along with the component evaluation/re-evaluation.

In a nutshell Case I. useEffect with dependency array having some values. useEffect(()=>{}, [ el1, el2, el3 ]) i) It will run once after the component renders for the very first time. ii) Again it will run after the component re-renders but only if the value of any of the dependencies changes. If the component re-renders but the value of any of the dependencies do not change then useEffect won’t run.(The component may re-render because of a change in state or props.) Case II. useEffect with empty dependency array. useEffect(()=>{},[ ]) It will run only once — after the component renders for the very first time. Case III. useEffect with no dependency array. useEffect(()=>{}) It is a valid syntax. It will run after the component renders and after every re-render of the component.

There are no different cases for react to handle useEffect.I made up these 3 cases only for the understanding purpose. Once you understand how useEffect works you will know that these cases are not actually different, they work on the same principle.

What elements should you use in the dependency array?

Key rule to add elements in the dependency array is : “Add all the variables/functions/states/props in your effect function which could change when your component or some parent component is re-rendered”

What you should not add as dependency —

No need to add state updating functions such as setValue. setValue function is never going to change even if the component re-renders.

No need to add built in functions like fetch as these will also never change.

*Very Important* Never add the states as dependencies which are being changed in the effect function. Otherwise it will cause an infinite loop.

const [value, setValue] = useState(false);

useEffect(() => {

console.log(“effect”);

setValue((prevState) => !prevState);

},[value]);

The above code is going to create an infinite loop — for the very first time the component will render and then useEffect will run which will change the state of value so the component will re-render again. Again the useEffect will run as value is a dependency and the state of value will be changed so the component will re-render again resulting in an infinite loop.

const [value, setValue] = useState(false);

useEffect(() => {

console.log(“effect”);

setValue((prevState) => !prevState);

}, []);

The above code will run only once after the first time the component renders. Thereafter the component will re-render because the state of value will be changed but useEffect won’t run again as the dependency does not change with respect to the previous execution of the cycle.