Rooks
HooksLifecycle & Effects

useDeepCompareEffect

Runs an effect when a dependency array changes by deep equality.

About

useDeepCompareEffect has the cleanup semantics of useEffect, but retains the previous dependency array while fast-deep-equal considers the next array equal. Use it for structural object dependencies that cannot be stabilized at their source.

Examples

import { useState } from "react";
import { useDeepCompareEffect } from "rooks";

export default function FilterSummary() {
  const [page, setPage] = useState(1);
  const filters = { page, sort: "name" };
  const [summary, setSummary] = useState("");

  useDeepCompareEffect(() => {
    setSummary(`Page ${filters.page}, sorted by ${filters.sort}`);
  }, [filters]);

  return (
    <section>
      <p>{summary}</p>
      <button type="button" onClick={() => setPage((value) => value + 1)}>
        Next page
      </button>
    </section>
  );
}

Parameters

ArgumentTypeDefaultMeaning
callbackEffectCallbackrequiredReact effect callback; it may return cleanup.
dependenciesDependencyListrequiredArray compared structurally between renders.

Passing a non-array value throws. An array containing only primitive values emits a development warning because ordinary useEffect is cheaper for that case.

Return value

The hook returns void.

Behavior and lifecycle

The effect runs after commit on mount and whenever the dependency array is not deeply equal to the previous retained array. React runs the prior cleanup before a changed effect and on unmount. Deep comparison happens during render and can be expensive for large or cyclic structures; fast-deep-equal does not make arbitrary cyclic graphs safe.

Compatibility and accessibility

No browser API is required, so the hook is safe to render on the server. Effects still do not run until the client commits. Accessibility depends on the side effect; avoid silently moving focus or changing visible state without an appropriate announcement.

On this page