Visualizing React re-renders for educational purposes
Learn how to build a custom debug component that visually highlights when React components re-render. This powerful technique helps identify performance bottlenecks and understand React's rendering behavior.

For my workshops (and for this blog), I like to show the renders of the components as they happen. This is a great way to understand how React works and how developers can optimize their applications. This has also helped me a lot in my preliminary work for my workshops to get a deeper understanding of how React does its magic.
In this article, I’ll show you how I build a custom debug component that visually highlights re-renders.
Contents
The Box component: how it works
Now, let’s look at how to build this debug component. I call it Box
because it
wraps around your components, creating a visual “box” that highlights when
re-renders occur.
Here’s the implementation:
import { useRef, useEffect } from "react";
/** * The Box Component displays a blinking outline when it re-renders */export function Box({ children, wrapperClassName, className, name = "Component", ...props}: React.HTMLProps<HTMLDivElement> & { name?: string; wrapperClassName?: string;}) { const ref = useRef<HTMLDivElement | null>(null); const renderCount = useRef(0);
renderCount.current += 1;
useEffect(() => { if (!ref.current) return; const originalBorder = ref.current.style.border; const originalBoxShadow = ref.current.style.boxShadow;
ref.current.style.border = "2px solid #8b5cf6"; ref.current.style.boxShadow = "0 0 12px 4px rgba(139, 92, 246, 0.5)";
const revert = () => { if (!ref.current) return; ref.current.style.border = originalBorder; ref.current.style.boxShadow = originalBoxShadow; };
const timer = setTimeout(revert, 200);
return () => { clearTimeout(timer); revert(); }; });
return ( <div ref={ref} {...props} className={`border-2 border-purple-500/30 bg-indigo-950/20 backdrop-blur-sm p-6 rounded-lg relative transition-all duration-200 shadow-md hover:shadow-lg ${wrapperClassName || ""}`} > <div className="absolute top-2 right-2 bg-gradient-to-r from-purple-700 to-indigo-700 text-white text-xs font-medium px-3 py-1 rounded-full shadow-sm" > {name} rendered: {renderCount.current} </div>
<div className={`pt-2 pb-2 ${className}`}>{children}</div> </div> );}
Let’s analyze the key parts of this component:
Tracking Render Count
I use a useRef
to persist the render count between renders. Each time the
component renders, we increment this counter and display it in the UI. This
gives us a visual indication of how many times a component has re-rendered.
const renderCount = useRef(0);renderCount.current += 1;
This is often quite useful, for instance, with React strict mode when a component renders twice in development mode.
Visual Highlight Effect
Then for the visual effect, I simply add a useEffect to add and remove a border
and a box shadow. It’s one of the rare cases where I use a useEffect
without a
dependency array as I want it to run on every render.
useEffect(() => { if (!ref.current) return;
const originalBorder = ref.current.style.border; const originalBoxShadow = ref.current.style.boxShadow;
ref.current.style.border = "2px solid #8b5cf6"; ref.current.style.boxShadow = "0 0 12px 4px rgba(139, 92, 246, 0.5)";
const revert = () => { if (!ref.current) return; ref.current.style.border = originalBorder; ref.current.style.boxShadow = originalBoxShadow; };
const timer = window.setTimeout(revert, 200);
return () => { revert(); window.clearTimeout(timer); };});
Using Box in a component
The usage is then quite simple. You just need to wrap your component with the
Box
and add a name
prop to identify the component. Here’s an example:
import { Box } from "./Box";
function Counter() { const [count, setCount] = useState(0);
return ( <Box name="Counter"> <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> </Box> );}
Et voilà!
We have a quite useful component for educational purposes. As a sidenote, I used it a lot in this good old repository react-sandboxes for my workshops.
Feel free to use it in your own projects or adapt it to your needs.