DEV Community

Cover image for Stop Re-Rendering! 7 Practical Ways to Optimize React Performance
Rayan Hossain
Rayan Hossain

Posted on

Stop Re-Rendering! 7 Practical Ways to Optimize React Performance

Introduction

Performance is one of the most crucial aspects of building modern web applications. In React, a common bottleneck is unnecessary re-renders, which can slow down apps, increase memory usage, and hurt user experience.

The good news? With a few smart techniques, you can significantly optimize React performance and make your applications run smoothly.

In this article, we’ll go over 7 practical tips to stop unnecessary re-rendering in React.


Why Performance Matters in React

  • Faster load times improve user experience
  • Optimized apps reduce memory usage
  • Better performance means higher SEO rankings
  • Smooth interactions = happier users

Unnecessary re-renders are one of the most common culprits behind poor performance. Let’s fix that.


1️⃣ Use React.memo for Pure Functional Components

If your component always renders the same output given the same props, you can wrap it with React.memo.

import React from "react";

const Button = ({ onClick, label }) => {
  console.log("Rendered:", label);
  return <button onClick={onClick}>{label}</button>;
};

export default React.memo(Button);
Enter fullscreen mode Exit fullscreen mode

✅ Great for pure functional components that receive the same props frequently.
⚠️ Avoid overusing it, as unnecessary memoization can add overhead.


2️⃣ Optimize Props with useCallback & useMemo

Functions and objects in JavaScript are reference types. Passing new references as props causes re-renders.

  • useCallback → Memoize functions
  • useMemo → Memoize values
import React, { useState, useCallback, useMemo } from "react";

function App() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  const expensiveValue = useMemo(() => {
    return count * 2;
  }, [count]);

  return (
    <div>
      <button onClick={handleClick}>Increase</button>
      <p>Expensive Value: {expensiveValue}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

✅ Use useCallback for event handlers
✅ Use useMemo for expensive calculations
✅ Prevents unnecessary re-renders in children.
✅ Great for performance-heavy calculations.


3️⃣ Split Code with React.lazy & Suspense

Large bundles increase initial load time. Code-splitting with React.lazy helps load components only when needed.

import React, { Suspense, lazy } from "react";

const Dashboard = lazy(() => import("./Dashboard"));

function App() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Dashboard />
    </Suspense>
  );
}
Enter fullscreen mode Exit fullscreen mode

✅ Improves initial page load speed
✅ Users only download what they need
✅ Improves Core Web Vitals for SEO.


4️⃣ Virtualize Long Lists with react-window / react-virtualized

Rendering thousands of DOM elements at once is costly. Use list virtualization to render only what’s visible.

import { FixedSizeList as List } from "react-window";

const Row = ({ index, style }) => (
  <div style={style}>Row {index}</div>
);

function App() {
  return (
    <List height={400} itemCount={1000} itemSize={35} width={300}>
      {Row}
    </List>
  );
}
Enter fullscreen mode Exit fullscreen mode

✅ Efficiently handles large datasets
✅ Reduces memory usage and re-renders


5️⃣ Avoid Anonymous Functions in JSX

Defining functions inside JSX causes a new function instance on every render, which may trigger re-renders.

❌ Bad Practice:

<button onClick={() => setCount(count + 1)}>Click</button>
Enter fullscreen mode Exit fullscreen mode

✅ Good:

const handleClick = () => setCount(count + 1);

<button onClick={handleClick}>Click</button>
Enter fullscreen mode Exit fullscreen mode

✅ Avoids new references on each render.
✅ Works great with React.memo.


6️⃣ Key Usage Best Practices in Lists

Incorrect key props can cause React to re-render unnecessarily.

✅ Always use unique and stable keys:

{users.map(user => (
  <UserCard key={user.id} user={user} />
))}
Enter fullscreen mode Exit fullscreen mode

❌ Avoid using array indexes as keys (except for static lists).


7️⃣ Performance Profiling with React DevTools

Before optimizing blindly, use the React DevTools Profiler to measure performance.

Steps:

Install React DevTools extension

Switch to the Profiler tab

Record interactions to see which components re-render unnecessarily

✅ Helps you focus only on real bottlenecks


🎯 Conclusion

Optimizing React performance doesn’t mean prematurely adding complexity. Instead, focus on preventing unnecessary re-renders and loading only what’s required.

✅ Quick Recap of 7 Tips:

Use React.memo

Optimize with useCallback & useMemo

Split code with React.lazy & Suspense

Virtualize long lists

Avoid anonymous functions in JSX

Use proper keys in lists

Profile with React DevTools

👉 Remember: Always profile before optimizing—don’t fix what isn’t broken.

With these techniques, your React apps will feel faster, smoother, and more professional. 🚀

Top comments (0)