Back to Blog
Lesson 40 of the React Fundamentals: Build Modern UIs from Scratch course
ReactJune 25, 20263 min read

Performance Optimization Basics: Mastering React Re-rendering

Performance optimization in React starts with understanding re-rendering. Learn how to identify bottlenecks and keep your UI responsive and fast.

Reactperformancere-renderingoptimizationweb-developmentjavascriptfrontend

Previously in this course, we explored introduction to proptypes-catching-bugs-with-react-type-checking to ensure our data flows correctly throughout our movie-browser app. Now that our components are robust, it’s time to ensure they are fast.

In React, "fast" often means avoiding unnecessary work. Today, we’ll dive into performance optimization by dissecting how React decides when to update the screen and how you can prevent the performance pitfalls that lead to sluggish UIs.

Understanding the Re-rendering Cycle

When you change state in a component, React schedules a re-render. This doesn’t mean the entire DOM is wiped and replaced—thanks to the understanding-the-virtual-dom-and-react-performance, React only updates what actually changed.

However, a "re-render" means React calls your function component again to see what it wants to return. If you have a complex component tree, a state change at the top can trigger a cascade of re-renders for every single child component, even if their specific props haven't changed. This is the primary source of "performance lag" in beginner React apps.

Identifying Bottlenecks

Before you start "optimizing," you must identify where the work is happening. The most common sign of a performance issue is a "stutter" during user interactions, like typing in a search bar or toggling a filter.

To see this in action, add a console.log at the top of your MovieCard component:

JSX
function MovieCard({ movie }) {
  console.log("Rendering MovieCard:", movie.title);
  return (
    <div className="card">
      <h3>{movie.title}</h3>
    </div>
  );
}

Now, open your browser console and interact with your app. If you change a filter or search, notice how many times "Rendering MovieCard" appears. If you have 50 movies, you’ll see 50 logs every time the parent component updates, even if only one movie card actually needs to change.

Basic Optimization Strategies

The golden rule of optimization is: don't optimize until you have a measurable problem. However, there are simple architectural habits that prevent these issues from growing.

1. Component Extraction

The most effective way to prevent unnecessary re-renders is to keep your state as "local" as possible. If a part of your UI doesn't need to change when a specific piece of state updates, move that UI into its own component.

2. Using React.memo

React.memo is a higher-order component that tells React: "If the props haven't changed, don't re-render this component." It performs a shallow comparison of the new props versus the old ones.

Let’s wrap our MovieCard:

JSX
import React from CE9178">'react';

const MovieCard = React.memo(({ movie }) => {
  console.log("Rendering MovieCard:", movie.title);
  return (
    <div className="card">
      <h3>{movie.title}</h3>
    </div>
  );
});

export default MovieCard;

Now, when the parent MovieList re-renders due to a filter change, React checks if the movie object reference is the same. If it is, it skips the MovieCard render entirely.

Hands-on Exercise: The "Expensive" Header

In your movie browser, create a Header component that displays the app title and a ThemeToggle button.

  1. Add a console.log to the Header component.
  2. Notice that every time you type in your search bar (which updates state in the parent), the Header re-renders, even though its content never changes.
  3. Wrap your Header in React.memo to prevent it from re-rendering when the search input state updates.

Common Pitfalls

  • Premature Optimization: Wrapping every single component in React.memo actually hurts performance. The comparison process itself has a cost. Only use it for components that render frequently or contain expensive logic.
  • Object/Array References: If you pass an object or array directly as a prop (e.g., style={{ color: 'red' }}), React sees a "new" object every render because the reference changes. This renders React.memo useless. Define these constants outside the component or use useMemo.
  • Ignoring the Key Prop: As we covered in the-key-prop-explained-mastering-react-lists-and-performance, using the wrong key (like an index) forces React to re-render list items unnecessarily. Always use stable, unique IDs.

Recap

Performance optimization is about reducing the workload during the render phase. By moving state closer to where it's used and selectively using React.memo for expensive components, you ensure your app remains responsive as it grows. Remember: observe, identify, then act.

Up next: We’ll explore how to handle browser history and navigation without page refreshes.

Similar Posts