Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
ReactNext.jsJune 20, 20264 min read

Profiling and fixing a slow React render: A Practical Guide

Profiling and fixing a slow React render is easier when you stop guessing. Learn how to use React DevTools to find bottlenecks and optimize your app.

ReactNext.jsPerformanceFrontendWeb DevelopmentTypeScript
Close-up of JavaScript code on a laptop screen, showcasing programming in progress.

Last month, our dashboard’s sidebar became sluggish during heavy data updates, causing a noticeable delay whenever a user toggled a filter. We were seeing interaction times spike to around 350ms, which is unacceptable for a snappy UI, so I spent two days deep-diving into the render cycle to figure out exactly what was eating our main thread.

Why profiling and fixing a slow React render matters

When your app grows, "it just works" stops being a viable strategy. You’ll eventually hit a wall where simple state updates trigger a cascade of re-renders across the entire component tree. Before you start wrapping everything in memo, you need to verify where the time is actually going.

I start by opening the React DevTools Profiler tab. I record a session, trigger the slow interaction, and stop the recording. Don't look at the flame graph first; look at the "Ranked" chart. It shows you exactly which components took the longest to render and, crucially, why they rendered. If a component re-rendered because its parent did, but its props didn't change, you’ve found your first target.

The wrong turn: Premature optimization

A wooden gate with humorous signs set in a rural landscape, expressing playful dissent.

My first instinct was to wrap every child component in React.memo. It felt like a quick fix, but it actually made the codebase harder to maintain and didn't solve the core issue. I was treating the symptoms, not the disease.

The real problem was state colocation. We were keeping our filterState at the top level of the Dashboard component. Every time a user changed a filter, the entire Dashboard—including the massive DataGrid—re-rendered. By moving the filter state into a dedicated FilterProvider or simply pulling it down into the Sidebar component, I limited the scope of the re-render.

If you're struggling with similar performance issues, understanding Streaming and Suspense in Next.js: Optimize Your Page Load can help you offload heavy logic, but for internal state, you have to be disciplined about where that state lives.

Fixing the bottleneck

Once I moved the state, I noticed the DataGrid was still re-rendering too often because of an unstable object reference passed as a prop. Here is how I refactored the parent component to stabilize the reference:

JAVASCRIPT
// Before: Unstable reference causes re-render
const Dashboard = () => {
  const [filters, setFilters] = useState({ category: CE9178">'all' });
  
  // This object is recreated on every render!
  const config = { sort: CE9178">'asc' }; 

  return <DataGrid config={config} />;
};

// After: Using useMemo to stabilize the reference
const Dashboard = () => {
  const [filters, setFilters] = useState({ category: CE9178">'all' });
  
  const config = useMemo(() => ({ sort: CE9178">'asc' }), []);

  return <DataGrid config={config} />;
};

This simple change prevented the DataGrid from re-rendering unless the config actually changed. Remember that Lists and keys in React: Why the console warnings matter is another common area where developers lose performance; if your keys are unstable, React has to destroy and recreate the entire list DOM, which is a massive performance killer.

When to stop optimizing

Creative display of the word 'OPTIMIZE' on a pink textured surface.

It's tempting to try and get every component to render in under 1ms, but that's a trap. If an interaction feels fast to the user, it’s fast enough. I usually aim for an interaction to complete in under 100ms.

If you are seeing slow performance even after memoizing components, check if your data fetching is the culprit. We often try to fix UI renders when the real issue is how we are Fetching data in a React component the right way. If your API calls are blocking the main thread or causing excessive waterfall requests, no amount of useMemo will save you.

FAQ: Common Profiling Questions

Q: Should I memoize every component by default? A: No. Memoization has a cost—React has to compare props on every render. Only memoize components that are expensive to render or re-render frequently due to parent state changes.

Q: How do I know if a component is "expensive"? A: Use the React DevTools Profiler. If a component takes more than 16ms to render, it’s a candidate for optimization.

Q: Does Next.js change how I should profile? A: Not fundamentally, but the Server/Client component boundary changes where you can apply these techniques. You can't memoize a Server Component, so focus your performance efforts on the Client Components where the interactivity lives.

I’m still not convinced we have the perfect balance in our current architecture. Sometimes I wonder if we’re over-engineering the state management instead of just simplifying the UI structure. Next time, I’ll probably start by removing features before I start adding performance optimizations. It’s usually faster to delete code than it is to optimize it.

Back to Blog

Similar Posts

Serene long exposure of a cascading waterfall surrounded by lush greenery in Shifen, Taiwan.
Next.jsReactJune 20, 20264 min read

Next.js App Router Data Fetching: Avoiding Performance Waterfalls

Learn how to master Next.js App Router data fetching by parallelizing server requests. Stop blocking your renders and fix performance waterfalls today.

Read more
Scrabble tiles spelling 'online store' on a rustic wooden background.
Next.jsReactJune 20, 20264 min read

Next.js Partial Prerendering: Optimizing Dynamic E-commerce Feeds

Next.js Partial Prerendering (PPR) lets you mix static and dynamic UI in one route. Learn how to optimize your e-commerce product feeds for instant loading.

Read more
A close-up view of a laptop displaying a search engine page.
Next.jsReactJune 20, 20264 min read

Streaming and Suspense in Next.js: Optimize Your Page Load

Master streaming and Suspense in Next.js to drastically improve perceived performance. Learn how to stream UI components for a faster, responsive experience.

Read more