JAVASCRIPT
Debugging React Re-renders with useWhyDidYouUpdate Hook
Identify and fix unnecessary React component re-renders using a custom `useWhyDidYouUpdate` hook, helping optimize performance and debugging.
import { useEffect, useRef, useState } from 'react';
function useWhyDidYouUpdate(name, props) {
const previousProps = useRef();
useEffect(() => {
if (previousProps.current) {
const allKeys = Object.keys({ ...previousProps.current, ...props });
const changes = {};
allKeys.forEach((key) => {
if (previousProps.current[key] !== props[key]) {
changes[key] = {
from: previousProps.current[key],
to: props[key],
};
}
});
if (Object.keys(changes).length) {
console.log('[why-did-you-update]', name, changes);
}
}
previousProps.current = props;
});
}
// Example Usage:
const ChildComponent = React.memo(({ count, data }) => {
useWhyDidYouUpdate('ChildComponent', { count, data });
return <p>Count: {count}</p>;
});
function ParentComponent() {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
useEffect(() => {
const interval = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
<button onClick={() => setOtherState(otherState + 1)}>Update Other State</button>
<ChildComponent count={count} data={{ value: 'test' }} />
</div>
);
}
How it works: The `useWhyDidYouUpdate` hook helps debug unnecessary re-renders in React components. It takes a component `name` and its `props`, then uses `useRef` to store the previous props. On each render, it compares the current props with the previous ones, logging any changes to the console. This highlights exactly which prop changed, triggering the re-render, aiding performance optimization.