Skip to content

useWhyDidYouUpdate

Logs prop differences to the console for debugging.

Logs prop differences to the console for debugging.

Import

import { useWhyDidYouUpdate } from '@kamod-ch/hooks'

Live demo

Basic demo

Logs prop differences to the console for debugging.

{
  "count": 0,
  "label": "draft"
}
No console log captured yet.
import { useEffect, useState } from 'preact/hooks'
import { useWhyDidYouUpdate } from '@kamod-ch/hooks'

function Child(props: { count: number; label: string }) {
  useWhyDidYouUpdate('WhyDidYouUpdateDemo', props)
  return <pre>{JSON.stringify(props, null, 2)}</pre>
}

export default function UseWhyDidYouUpdateDemo() {
  const [count, setCount] = useState(0)
  const [label, setLabel] = useState('draft')
  const [logs, setLogs] = useState<string[]>([])

  useEffect(() => {
    const original = console.log
    console.log = (...args) => {
      if (args[0] === '[why-did-you-update]') {
        setLogs((value) => [JSON.stringify(args.slice(1)), ...value].slice(0, 3))
      }
      original(...args)
    }
    return () => {
      console.log = original
    }
  }, [])

  return (
    <div>
      <Child count={count} label={label} />
      <div class="demo-actions">
        <button type="button" onClick={() => setCount((value) => value + 1)}>Change count</button>
        <button type="button" onClick={() => setLabel((value) => value === 'draft' ? 'published' : 'draft')}>Change label</button>
      </div>
      <pre>{logs.join('\n') || 'No console log captured yet.'}</pre>
    </div>
  )
}

API

TypeScript signature
export type IProps = Record<string, any>;
declare function useWhyDidYouUpdate(componentName: string, props: IProps): void;
export default useWhyDidYouUpdate;
/

SSR considerations

This hook is safe to import during SSR. If your effect body touches the DOM, keep that work inside the effect callback.

Browser compatibility

Works in any modern browser supported by Preact.