Front-end Reactor: useEffect in Action

ยท

5 min read

Front-end Reactor: useEffect in Action

Introduction

React's built-in hook useEffect is used to manage side effects in a component, We use useEffect when we want a specific piece of code to execute as a result of a change in some dependency (change in variable or function).

Render Logic- The part of the component which gets executed as soon as a component is rendered and is responsible for UI rendering.

Side Effects- The part of the component which has interaction outside the component, such as HTTP request, DOM manipulation or setting up timers.

Side effects are commonly managed and controlled within React components using event handlers and the useEffect hook.

๐Ÿ’ก
This is the third blog in the Front-end Reactor series. Don't forget to check out my previous blog on States in React

What if Side Effects are in Render Logic

Including side effects in render logic can lead to performance issues and unexpected behavior, that's why side effects are isolated from render logic

Suppose we fetch some data in the render logic

function Component(){
const [fetchData,setFetchData]=useState([]);
//Fetching
fetch('https://api.example.com/data')
.then((res)=>res.json())
.then((data)=>setFetchData(data));
return <div>{fetchData}</div>
}

This will lead to an infinite loop of GET requests, when the component is mounted, it initiates data fetch and updates the state, As a result, the component is re-rendered, causing data fetch and update. Therefore this leads to infinite re-render and requests.


useEffect Syntax

The useEffect hook requires 2 arguments, the first argument is a function that contains the side-effect code and the second argument is a dependency array, it contains the dependency which when changed triggers the effect to run.

๐Ÿค“
FOR NERDS: Effect callback are synchronous to prevent race condition
import {useEffect} from 'react'
function Component(){
useEffect(function(){
// side-effects
},[]); // []-> dependency Array

return <div>useEffect is awesome</div>
}

Dependency Array

Dependency arrays act as a method to determine when an effect should be executed, this array is passed in useEffect hook as an argument to prevent it from running after each render, after each render react compares the current values of the dependencies with their previous values, if there is change the effect is executed again.

So basically all the states and props used in the Effect function should be added to the dependency array so that components are synchronized to the side-effects.

There are total 3 conditions

  1. No dependency Array

     useEffect(function(){
     // side-effect
     });
    

    In this case, the effect is executed each time the component is rendered, as the dependency array is absent.

  2. Empty Dependency Array

     useEffect(function(){
     // side-effect
     },[]);
    

    In this case, there are no dependencies so the effect is only executed once after the component is mounted

  3. Dependency Array

     const [count1,setCount1]=useState(0);
     const [count2,setCount2]=useState(0);
     const [count3,setCount3]=useState(0);
     useEffect(function(){
     document.title=count1+count2+count3;
     },[count1,count2,count3]);
    

    In this case, we have count1, count2 & count3 as dependencies, Firstly the effect is executed after mount secondly each time any one or more of the dependencies is updated the effect is executed and the title of the page is updated


Chronology

At first, while the component is mounted the effect is not executed immediately, it is executed only after a component is rendered in UI, otherwise before rendering the UI the side effect could have blocked the code

useEffect(function(){
console.log("First");
},[]);

console.log("Second");

useEffect(function(){
console.log("Third")
});

On initial render we will be surprised to see, the order of the consoled value is different

//Initial Render
Second
First
Third

//Re-render
Second
Third

Here Second is part of the render logic and it is consoled during mounting and the effects are run after mounting that's why it is in this order.


Cleanup Function

Effects provides a method to clean up the effects which are no longer needed, we can provide a cleanup function by just returning a function from an effect. This is optional for some cases but is important in many, where it may lead to memory leaks.

This cleanup is executed in 2 cases-

  • Before the Effect is executed again due to a change in the dependency array, to reset the result of the previous side effect.

  • After the component is unmounted, to reset the result of the side effect.

This cleanup step ensures that any resources, event listeners, or subscriptions created by the effect are properly removed.

HTTP Req must have a cleanup to cancel the request and an added Event Listener must have a cleanup to remove the event listener.

For example, here we change the title of a react app based on a count state variable -

function Title() {
  const [count, setCount] = useState(0);

  useEffect(function {
    document.title = `Count: ${count}`;
    return function{
      document.title = 'React App'; 
    };
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

When the component unmounts or before the effect runs again, the cleanup function will reset the document title to 'React App'


Best Practices

  • Each effect must have a specific responsibility, instead of having all side effects in one effect, create individual effects.

  • All the state and prop used in the effect must be in the dependency array, otherwise react will have no idea when to execute the effects

  • Always provide a cleanup function to reset the results of the side effects.

  • useEffect must be at the top level of the component, not after early return or inside conditions


Conclusion

In conclusion, we can say useEffect ensures things happen at the right times, like fetching data when needed, updating the screen, or cleaning up after itself.

I hope this blog, gives a basic idea of Effects

Till Next Time!


Connect With Me ๐Ÿ”—

If you're interested in topics like React.js, JavaScript or Web Development in General, Let's Connect!

LinkedIn: Click Here

Twitter: Click Here

ย