The beautiful useEffect React Hook

Sanjar Kairosh
December 9th, 20203 min read
Photo by Ivan Timov

The beautiful useEffect React Hook

ivan-timov-b_Za9cgcTKA-unsplash.jpg

Photo by Ivan Timov on Unsplash

useEffect is for side effects

useEffect is to functional components what componentDidMount , componentDidUpdate , and componentWillUnmount are, combined, to class components. It is a method responsible for all the so-called side effects that occur during the lifecycle of a React component.

Whether you want to make a call to an API, manipulate the DOM, or set up a subscription to sockets, useEffect is where all of that should take place.

const App = () => {
  
  useEffect(() => {
    
    axios.get('/')
      .then(resp => console.log(resp))
      .catch(err => console.log(err));
    
  });
  
  
  //   manipulate DOM
  useEffect(() => {
    document.getElementById("someElement").addEventListener('click', someFunction);
  });
  
  
  // subscribe to sockets
  useEffect(() => {
    const socket = socketIOClient("endpoint");
    socket.on("data", data => {
      // do something with data
    });
  )}
 
  return(
    <div>
      Content Here
     </div>
  )
}

useEffect is invoked on every render

Every single time your component re-renders, the useEffect hook is invoked anew. But what if you don’t want that to happen? What if you want to skip effects?

You can achieve that by instructing React to watch if certain values have changed between re-renders.

useEffect(() => {
}, [dependencies]);

The first argument to the useEffect method is the function to execute. The second argument is the dependency array. This is key to skipping effects.

The dependency array

On every render, React takes a look at the dependency array, and compares it to the one from the previous render. If at least one of the elements in the array has changed, React will execute the effect again. If no element has changed, React skips the effect.

Usually, props or state go in the dependency array. Sometimes functions too. Anything the process depends on should be included in the dependency array.

If you want the effect to run only once, set the second argument of useEffect as an empty array[] . This tells React that the effect does not depend on any values. That it should be run a single time, on the very first render of the component.

useEffect(() => {
    // something here
},[]);

Don’t forget to clean-up after yourself

Once side-effects such as manipulating the DOM, or subscribing to sockets are carried out, it is imperative to clean-up after yourself by unsubscribing to avoid any unintentional memory leaks!

When you add a click event listener to a DOM element, you should remove the event listener after the lifecycle of the component ends. After the component disappears, a socket connection remains active. You must disconnect from the socket.

The clean-up is accomplished via the return function in useEffect. React will run it when the component disappears from the DOM.

const App = () => {
  
  
  //   remove event listener when component goes away
  useEffect(() => {
    document.getElementById("someElement").addEventListener('click', someFunction);
    
    // clean up
    return () => {
      document.getElementById("someElement").removeEventListener('click', someFunction); 
    };
  });
  
  
  // unsubscribe from socket when component goes away
  useEffect(() => {
    const socket = socketIOClient("endpoint");
    socket.on("data", data => {
      // do something with data
    });
    
    // clean up
    return () => {
      socket.disconnect();
    };
  )}
 
  return(
    <div>
      Content Here
     </div>
  )
}

When the component lifecycle ends, React will call the return function both to remove the event listener and to close the socket connection.


Conclusion

useEffect is so flexible. If you need to run an effect once on the first render, no problem. If you need to run the effect sometimes, but skip it on other occasions, no problem as well. If you need to run it all the time, no questions asked. It is also very convenient to ensure clean-up within the same useEffect hook, rather than writing a separate extra method.

I believe the above information is enough to comfortably employ the useEffect hook in your React code. If you want a deep dive into useEffect consider this incredible piece by Dan Abramov.

Blogs

copyright ©2021 all rights reserved, Sanjar Kairosh
illusrations by icons8