useEffect Hook: React

useEffect Hook: React

Well, what does this useEffect Hook does?

To simply put, it helps us to do something after our component has rendered. React will run this after it has updated the DOM. So useEffect does not block the browser from rendering, but it is run after perfoming the DOM updates. useEffect takes two parameters: function and an optional dependancy array. We will talk about the secondary parameter in a bit.

Syntax:

useEffect(() => {
  // Something here..
})

useEffect should be called inside a function component, and ensure you call it on top level of your React function.

By default this useEffect runs on every render/update.
Now if you use a timer function in useEffect, its going to render like forever.

Check it out:

import React, { useEffect, useState } from "react";

const Example = () => {
  const [ count, setCount ] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>I've rendered {count} times!</h1>
}
export default Example;

First time after the page is rendered, useEffect Hook runs, which updates the count state, now because there is a new update, useEffect runs again which in turn updates the state again, and this loop goes on!

But, hey I don't want to run it everytime!

Now this is when we use the optional secondary parameter, the dependency array.

The dependancy array can be either set to empty or you can pass a value or multiple values.

If you just want it to run only once after the component has rendered, use an empty array, which will be in most cases I think.

useEffect(() => {
// runs once
},[])

Now if we take the same timer, it won't run forever, but only once because of the empty dependency array.

Hmm, so it will run the useEffect Hook whenever there is render and only once. But what if I only want it to run when a specific value has changed, say only when the count state has changed..? Say you have many other states other than count, if you use an empty dependency array, if there is an update/change to any other state, this will cause a re-render and the useEffect hook will run once as before.

Now to only run it when say count state changes, we can pass that state inside the dependency array! Now useEffect will only run when that specific state in the dependency array is changed, regardless of other state changes/renders. You can also pass multiple values to the dependency array, separated by commas.

To Summarise:

useEffect(() => {
  //Runs on every render
});

useEffect(() => {
  //Runs only on the first render
}, []);

useEffect(() => {
  //Runs on the first render
  //And any time any dependency value changes
}, [state, prop]);

Cleaning Up the useEffect

Some times we need to clean up the Hook to reduce memory leaks. Functions that are no longer needed like timeouts, subscriptions, event listeners etc., (these are also called side-effects) should be disposed.

How? By including a return function at the end of the useEffect Hook.

  useEffect(() => {
    let timer = setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);

    return () => clearTimeout(timer);
  }, []);

Woohoo, that was a quick take on useEffect Hook.

Any feedbacks/doubts please use the comment box. Let's connect on twitter

Did you find this article valuable?

Support Mansoor Ameen by becoming a sponsor. Any amount is appreciated!