Try @eslint-react/kit@beta
logoESLint React

no-leaked-resize-observer

Enforces that every 'ResizeObserver' created in a component or custom hook has a corresponding 'ResizeObserver.disconnect()'.

Full Name in eslint-plugin-react-web-api

react-web-api/no-leaked-resize-observer

Full Name in @eslint-react/eslint-plugin

@eslint-react/web-api-no-leaked-resize-observer

Presets

web-api recommended recommended-typescript recommended-type-checked strict strict-typescript strict-type-checked

Rule Details

Creating a ResizeObserver without disconnecting it can lead to memory leaks and unexpected behavior.

Examples

Creating ResizeObserver without disconnecting in useEffect

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

function MyComponent() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current) return;
    // Problem: A 'ResizeObserver' in 'useEffect' should have a corresponding 'resizeObserver.disconnect()' in its cleanup function.
    const ro = new ResizeObserver(() => console.log("resize"));
    ro.observe(ref.current);
  }, []);

  return <div ref={ref} />;
}

Disconnecting ResizeObserver in useEffect cleanup

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

function MyComponent() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current) return;
    // Recommended: Create and use ResizeObserver
    const ro = new ResizeObserver(() => console.log("resize"));
    ro.observe(ref.current);
    // Recommended: Disconnect in the cleanup function
    return () => ro.disconnect();
  }, []);

  return <div ref={ref} />;
}

Observing multiple elements with ResizeObserver

When observing multiple elements, disconnect the observer in the cleanup function to prevent memory leaks.

// Recommended: Disconnect ResizeObserver when observing multiple elements
import { useEffect, useRef } from "react";

function ResizablePanels() {
  const panelARef = useRef<HTMLDivElement>(null);
  const panelBRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const ro = new ResizeObserver((entries) => {
      for (const entry of entries) {
        console.log("Size changed:", entry.contentRect);
      }
    });

    if (panelARef.current) ro.observe(panelARef.current);
    if (panelBRef.current) ro.observe(panelBRef.current);

    return () => ro.disconnect();
  }, []);

  return (
    <>
      <div ref={panelARef}>Panel A</div>
      <div ref={panelBRef}>Panel B</div>
    </>
  );
}

Versions

Resources

Further Reading


See Also

On this page