Rooks
HooksUI & Layout

useMutationObserver

Observes mutations on the element in an existing object ref and cleans up automatically.

About

useMutationObserver connects the browser's MutationObserver to an element already held in a mutable object ref. Use it when the ref's target is stable and raw mutation records are needed.

Example

import { useCallback, useRef, useState } from "react";
import { useMutationObserver } from "rooks";

export default function MutationCount() {
  const targetRef = useRef<HTMLDivElement | null>(null);
  const [expanded, setExpanded] = useState(false);
  const [mutationCount, setMutationCount] = useState(0);
  const onMutation = useCallback<MutationCallback>((records) => {
    setMutationCount((count) => count + records.length);
  }, []);

  useMutationObserver(targetRef, onMutation);

  return (
    <section>
      <div ref={targetRef}>
        {expanded ? <strong>Expanded content</strong> : "Compact content"}
      </div>
      <button type="button" onClick={() => setExpanded((value) => !value)}>
        Change observed content
      </button>
      <p aria-live="polite">Observed mutation records: {mutationCount}</p>
    </section>
  );
}

Parameters

ParameterTypeDefaultDescription
refMutableRefObject<HTMLElement | null>requiredRef whose current element is observed when the effect runs.
callbackMutationCallbackrequiredReceives mutation records and the observer.
optionsMutationObserverInitall common mutation kindsPassed to observer.observe().

The default options set attributes, characterData, childList, and subtree to true.

Return value

Returns void.

Behavior and lifecycle

When the effect sees ref.current, it creates one observer and observes that node. It disconnects when the ref object, callback, or options identity changes and on unmount. Keep inline callbacks and options stable with useCallback or useMemo when repeated observer creation is undesirable.

The effect depends on the ref object, not changes to .current. For a conditionally mounted or replaceable node, prefer useMutationObserverRef, whose callback ref makes node changes observable to React. Exceptions from the callback are not caught.

The browser also throws when an options object requests no mutation kind; that observation error is not caught.

Compatibility and accessibility

The hook is server-safe while the ref is empty because observer creation happens in an effect. A browser without MutationObserver needs a polyfill before the ref resolves to an element.

Mutation records describe DOM changes, not user intent. Avoid using them as the only signal for status announcements, validation, or focus management; update accessible state explicitly when the application performs the change. See SSR and browser APIs.

On this page