Optimized

React.memo()

const Memoized = React.memo(Component)

A higher-order component that skips re-rendering if props stay the same. It's like a shield against unnecessary updates.

React.memo()

A Higher-Order Component (HOC) for performance optimization. It prevents a functional component from re-rendering if its props haven't changed.

The Render Cascade

By default, when a Parent re-renders, ALL its children re-render too. Even if their props are identical. For large trees, this is costly.

Opting Out

React.memo wraps your component and adds a check: 'Did the props change shallowly?'. If not, it skips the render and reuses the last result.

The Object Trap

Beware! Objects and arrays are compared by reference. If you create a new object inside the render function, React.memo sees it as a 'new' prop.

Live Comparison

Update the parent's unrelated state. Watch how the Regular Child re-renders wastefully, while the Memoized Child stays quiet.

Default Behavior

Every time Parent renders, Child renders too. Even if name is exactly the same.

DefaultRender.tsx
function Child({ name }) {
  console.log("Child rendered"); // Runs every time Parent updates!
  return <div>Hello {name}</div>;
}

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

  return (
    <>
      <button onClick={() => setCount(c => c + 1)}>
        Count: {count}
      </button>
      <Child name="Alice" /> 
    </>
  );
}
Unnecessary re-renders

The Solution

Wrap the child in React.memo. Now, if the parent updates but name stays "Alice", the child assumes nothing changed and skips render.

MemoizedChild.tsx
import React, { memo } from 'react';

const Child = memo(({ name }) => {
  console.log("Child rendered"); // Only runs if 'name' changes!
  return <div>Hello {name}</div>;
});

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

  return (
    <>
      {/* Updating 'count' triggers Parent render... */}
      <button onClick={() => setCount(c => c + 1)}>
        Count: {count}
      </button>
      
      {/* ...but Child is memoized and 'name' is static, so it skips! */}
      <Child name="Alice" /> 
    </>
  );
}
Using React.memo

The Object Trap

React.memo uses shallow comparison. If you pass a new object or function every time, it will think props changed and re-render anyway.

BrokenMemo.tsx
function Parent() {
  const [count, setCount] = useState(0);

  // 🔴 DANGER: This object is RE-CREATED on every render!
  // { name: "Alice" } !== { name: "Alice" } (Referential Equality)
  const user = { name: "Alice" }; 

  return (
    <>
      <button onClick={() => setCount(c + 1)}>Count</button>
      
      {/* React.memo does a shallow check: prevProps.user === nextProps.user */}
      {/* Since 'user' is a new reference, the check FAILS and Child re-renders. */}
      <MemoizedChild user={user} />
    </>
  );
}
Referential equality matters!
Tip: Use useMemo or useCallback to keep props stable so React.memo can do its job.
AlgoAnimator: Interactive Data Structures