Pure Components - memo
by Tomas Trescak· Advanced React

Root Folder
Not Attempted
NameProgress
Introduction
Not Read
🍰 Player
Not Read
Setup
Not Attempted
NameProgress
Software Installation
Not Read
Project Setup
Not Read
Running and Testing
Not Read
React and ReactDOM
Not Read
đź’ˇ Assignment 1: Welcome Message
Not Attempted
Submissions
Not Read
React
Not Attempted
NameProgress
JSX and Components
Not Read
Props
Not Read
đź‘ľ Exercise: Props
Not Attempted
CSS Styles
Not Read
useState and Hooks
Not Read
đź‘ľ Exercise: useState
Not Attempted
Conditional Rendering
Not Read
Lists
Not Read
đź‘ľ Exercise: Lists
Not Attempted
Forms and Events
Not Read
đź‘ľ Exercise: Forms
Not Attempted
đź’ˇ Assignment 2: Front End
Not Attempted
Pure Components - memo
Lifecycle - useEffect
Expensive? - useMemo
DOM Interactions - useRef
forwardRef
useImperativeHandle
đź‘ľ useImperativeHandle
Not Attempted
Context
useCallback
useId
useReducer
Infrastructure
Not Attempted
NameProgress
Database
Not Read
NextAuth and Github Authentication
Not Read
Prisma and ORM
Not Read
Project Setup
Not Read
Project Authentication
Not Read
APIs
Not Attempted
NameProgress
APIs
Not Read
APIs - Slides
Not Attempted
Rest APIs
Not Read
Rest APIs - Express.js
Not Read
ReastAPIs - Next.js
Not Read
Securing APIs
Not Read
Securing APIs - NextAuth
Not Read
tRPC
Not Attempted
NameProgress
tRPC
Not Read
tRPC - Routers
Not Read
tRPC - Server Rendering
Not Read
tRPC - Client Rendering
Not Read
Persisting Data
Not Read
Assignment 3: APIs
Not Read
0 / 300 XP

Lecture Transcript
If you prefer text to video, check out the transcript of the presentation above

By now, you learned how to build pretty complex applications. But, as the complexity of your application grows, you need to be aware of how to optimise it when it starts to become sluggish.

Often, the problem is the number of unnecessary re-renders. Let’s first create a scenario where a child component re-renders every time the parent component re-renders, even if its input (props) remains unchanged.

How this works? The ParentComponent holds a count state and provides a button to increment this count. Each time the button is clicked, setCount triggers a re-render of the ParentComponent

The NonPureComponent is a simple functional component that displays a message prop. Even though the message prop remains constant, the child component is re-rendered every time the parent updates its state.

When you interact with the button, you will notice that console-log statement runs every time, even though the message prop hasn’t changed. This happens because React functional components are not "pure" by default—they re-render when their parent re-renders. While a simple example like this doesn’t cause noticeable issues, in larger applications, unnecessary renders can lead to Performance Bottlenecks and Unintended Side Effects.

We can solve this problem by wrapping the child component with React-memo, a higher-order component that optimises functional components by preventing re-renders when props don’t change.

How does it work? By wrapping the functional component with React-memo, React compares the new props with the previous props. If the props haven’t changed, React skips re-rendering the component. In our example, when you increment the count in ParentComponent, PureComponent no longer re-renders because its message prop doesn’t change.

But, if we include the value of the count as a prop of our Pure component ...

... as expected, clicking on the button will trigger a re-render for each click.

Description
All the extra information about this section

By now, you learned how to build pretty complex applications. But, as the complexity of your application grows, you need to be aware of how to optimise it when it starts to become sluggish. Often, the proble is the number of unnecessary re-renders. Let’s first create a scenario where a child component re-renders every time the parent component re-renders, even if its input (props) remains unchanged.

Non-Pure Component Example

import React from 'react';

const NonPureComponent = ({ message }) => {
  console.log('NonPureComponent rendered');
  return <div>{message}</div>;
};

const ParentComponent = () => {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count: {count}</button>
      <NonPureComponent message="Hello from Non-Pure Component!" />
    </div>
  );
};

export default ParentComponent;

How This Works

  1. Parent Component:
    • The ParentComponent holds a count state and provides a button to increment this count. Each time the button is clicked, setCount triggers a re-render of the ParentComponent.
  2. Child Component:
    • The NonPureComponent is a simple functional component that displays a message prop.
    • Even though the message prop remains constant, the child component is re-rendered every time the parent updates its state.

When you interact with the button, you will notice that console.log('NonPureComponent rendered') runs every time, even though the message prop hasn’t changed. This happens because React functional components are not "pure" by default—they re-render when their parent re-renders.

Why This is a Problem

While a simple example like this doesn’t cause noticeable issues, in larger applications, unnecessary renders can lead to:

  • Performance Bottlenecks:
    • If a component performs expensive computations or renders a large DOM subtree, re-rendering it unnecessarily can slow down your app.
  • Unintended Side Effects:
    • If the component uses useEffect or other hooks tied to rendering, these might be triggered even when they aren’t needed, leading to bugs or inefficient behavior.

Introducing React.memo: Making the Component Pure

We can solve this problem by wrapping the child component with React.memo, a higher-order component (HOC) that optimizes functional components by preventing re-renders when props don’t change.

Pure Component with React.memo

import React from 'react';

const PureComponent = React.memo(({ message }) => {
  console.log('PureComponent rendered');
  return <div>{message}</div>;
});

const ParentComponent = () => {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count: {count}</button>
      <PureComponent message="Hello from Pure Component!" />
    </div>
  );
};

export default ParentComponent;

How React.memo Works

  1. Memoizing the Component:
    • By wrapping the functional component with React.memo, React compares the new props with the previous props.
    • If the props haven’t changed, React skips re-rendering the component.
  2. Behavior Change:
    • In this example, when you increment the count in ParentComponent, PureComponent no longer re-renders because its message prop doesn’t change.

You can observe this in the console—console.log('PureComponent rendered') only runs on the initial render and does not trigger again, even when the parent updates.


Why Using React.memo is Important

1. Performance Optimization

By reducing unnecessary renders, React.memo helps optimize your application’s performance. In real-world applications with deep component trees or computationally expensive operations, avoiding redundant renders can make a significant difference.

2. Improved Predictability

Using React.memo enforces a more predictable rendering behavior. Developers can reason more easily about when a component will re-render, based on changes to its props.

3. Resource Efficiency

For components that perform heavy rendering logic (e.g., complex calculations, rendering lists with thousands of items), React.memo ensures that they only render when their inputs (props) change, reducing the CPU workload.


When to Use React.memo

While React.memo is a powerful tool, it’s essential to use it judiciously:

  • Use it for Components that Don’t Change Often:
    • Components that only re-render when their props change are the best candidates.
  • Avoid Overuse:
    • Wrapping every component in React.memo can add unnecessary complexity and marginal performance gains in simple components.

Conclusion

React.memo is a simple yet powerful optimization tool for functional components. It allows you to transform impure components, which re-render unnecessarily, into pure components that only re-render when required. This not only improves your app's performance but also makes its behavior more predictable and resource-efficient. By understanding and strategically using React.memo, you can build React applications that scale effectively without compromising on performance or maintainability.

Maggie

Discuss with Maggie
Use the power of generative AI to interact with course content

Discussion

0 comments
Loading editor ...
Remember to be polite and report any undesirable behaviour

Category

Empty

Labels

Discussion has no labels

1 participant

user avatar

Priority

Notifications

You're not receiving notifications from this thread.
Course Outline