DEV Community

Cover image for React Performance: Small Fixes That Made a Big Impact
Arpy Vanyan
Arpy Vanyan

Posted on

24

React Performance: Small Fixes That Made a Big Impact

When you're building the first version of a React app, performance usually isn’t your top concern. Things feel snappy. It’s just React, right?

Then, the app grows. New features get added, state becomes more complex, components nest deeper, and before you know it, something that used to be smooth starts to feel... sluggish.

I’ve been there. Below are some of the most practical performance lessons I’ve learned while scaling React apps—things I wish I’d done earlier, and fixes that made a noticeable difference without overcomplicating the codebase.


1️⃣ Measure Before You Optimize

It sounds obvious, but it’s often skipped. I used to reach for useMemo or React.memo way too early without knowing what was actually slowing things down.

What actually helps:

🔍 React DevTools Profiler – Spot unnecessary re-renders.

📦 why-did-you-render – Understand what's rendering and why.

⚙️ Lighthouse – Useful for performance audits and slow paints.

🧪 Real user feedback – Often the best indicator something’s off.

Takeaway: Don’t guess. Measure first, then optimize what’s actually slow.


2️⃣ Too Many Renders? Check Your State

One of the biggest performance drains I’ve seen is over-rendering caused by lifted state. It’s tempting to keep things high up in the tree “just in case” other components need access, but that can end up re-rendering the entire subtree.

What helped:

  • Keep state as close to where it’s used as possible.
  • Use derived state with memoization.
  • Apply React.memo only where it helps (after profiling).

Takeaway: Overlifting state leads to over-rendering. Start local, move it up only if needed.


3️⃣ useEffect Isn't Your Friend (Most of the Time)

In early projects, I used useEffect for everything: fetching data, syncing state, firing side effects. It worked, but it led to complexity and subtle bugs.

What I changed:

  • Stopped using effects for things that could be derived or handled declaratively.
  • Moved server state logic to State Manager.
  • Created custom hooks to isolate repeated logic.

Takeaway: Reach for useEffect only when there's no better alternative.


4️⃣ Initial Load Times Matter More Than You Think

If your app feels slow to open, users notice. I’ve seen apps load the entire dashboard even when the user just needs the login screen.

What helped:

  • ✂️ Code splitting routes using dynamic import() and React.lazy.
  • 🧹 Tree shaking unused code and libraries.
  • ⚛️ Breaking up giant components into smaller, focused ones.
  • 📊 Using tools like webpack-bundle-analyzer to see what’s in your bundle.

Takeaway: Don’t serve the whole app upfront. Load what the user needs, when they need it.


5️⃣ Lists Are a Performance Trap

Large lists rendered the wrong way will quietly wreck performance. One project had a simple dropdown with 1000+ items rendered without virtualization—it completely froze the UI.

What helped:

  • Used react-window to only render visible list items.
  • Avoided anonymous functions inside .map() calls.
  • Used unique keys (not index) to avoid re-rendering issues.

Takeaway: Lists need extra care. Optimize them early.


6️⃣ Real Debug Example: The Mystery Re-Render

The same seemingly innocent Dropdown component was triggering re-renders across the whole page. It was tied to a parent’s state via props, and every dropdown change re-rendered multiple unrelated charts.

Fix:

  • Memoized the dropdown to isolate re-renders.
  • Split state into smaller, targeted slices.
  • Removed lifted state chain and used shared redux state.

Result: Charts became responsive again, and interaction time dropped by ~200ms.


🧠 Final Thoughts

React performance isn’t about overusing useMemo or blindly adding caching. It’s about understanding how your app renders, keeping things simple, and avoiding unnecessary work.

Start small. Measure. Fix what matters first.

Often, it’s basic architectural decisions—where state lives, how components are composed, how data flows—that have the biggest impact over time.

Neon image

Set up a Neon project in seconds and connect from a Next.js application

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started →

Top comments (0)

Neon image

Next.js applications: Set up a Neon project in seconds

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started →

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay