Cleanup callback of useEffect

  • React
  • Examples
  • Cleanup callback of useEffect

React example • 2 min read

  • useEffect

Cleanup of window event listeners

In this sample, we have a component named WindowSize that updates its state with the window width and height every time there is a window resize event. To achieve this, we take advantage of the useEffect hook with an empty dependency array (so that it would only run on the mount and unmount, being the mount the body of the callback function, and the unmount the return of that callback).

Every time we use a window.addEventListener() function inside a useEffect hook, we should remember to remove that window event listener when the component gets unmounted, so that we are not constantly adding global event listeners and possibly having memory leaks.

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

function WindowSize() {
  const [size, setSize] = useState({
    width: 0,
    height: 0
  });

  useEffect(() => {
    // Define the listener callback function
    const onWindowResize = (event) => {
      setSize({
        width: event?.target?.innerWidth ?? window.innerWidth,
        height: event?.target?.innerHeight ?? window.innerHeight
      });
    };

    // Run event listener function on useEffect startup
    onWindowResize();

    // Add window resize event listener on useEffect startup
    window.addEventListener("resize", onWindowResize);

    return () => {
      // Remove window resize event listener on useEffect cleanup
      window.removeEventListener("resize", onWindowResize);
    };
  }, []);

  return (
    <p>
      Window width: {size.width}
      <br />
      Window height: {size.height}
    </p>
  );
}

export default WindowSize;

Cleanup of setInterval and setTimeout

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

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    // Start interval on useEffect startup
    const intervalId = setInterval(() => {
      setSeconds((prevSeconds) => prevSeconds + 1);
    }, 1000);

    return () => {
      // Clear the interval on useEffect cleanup
      clearInterval(intervalId);
    };
  }, []);

  return <div>Seconds passed: {seconds}</div>;
}

export default Timer;