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.