Rooks
HooksDevelopment & Debugging

useWhyDidYouUpdate

Logs tracked values whose identity changed between committed renders.

About

useWhyDidYouUpdate compares named values with their previous committed values and logs the differences. It is intended for finding unstable props and avoidable rerenders during development.

Examples

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

function Profile(props: { name: string; active: boolean }) {
  useWhyDidYouUpdate("Profile", props);
  return (
    <p>
      {props.name}: {props.active ? "active" : "inactive"}
    </p>
  );
}

export default function UpdateDebugger() {
  const [active, setActive] = useState(false);
  return (
    <section>
      <Profile name="Ada" active={active} />
      <button type="button" onClick={() => setActive((value) => !value)}>
        Toggle profile
      </button>
    </section>
  );
}

Parameters

ArgumentTypeDefaultMeaning
componentNamestringrequiredLabel included in the console message.
currentPropsRecord<string, unknown>requiredNamed values to compare.
enableLoggingbooleantrueSuppresses output while false.

The record type is shown inline because it is not a public type export from the package barrel.

Return value

The hook returns void.

Behavior and lifecycle

The first render stores values without logging. After later commits, the hook builds the union of previous and current keys and compares each value with Object.is. Changed keys are logged as { from, to } in one console.log("[why-did-you-update]", componentName, changedProps) call. Removed keys have to: undefined; added keys have from: undefined.

The previous snapshot updates after every commit even when logging is disabled. Object and array contents are not compared deeply, so a new reference counts as a change. React Strict Mode and concurrent rendering can produce development behavior that differs from production; use this as a clue, not a correctness signal.

Compatibility and accessibility

No browser-only API is required, though the output depends on console.log. Do not include secrets or personal information in tracked records. The hook does not affect the accessibility tree.

On this page