exequiel-sosa
alal
← Back to blog
[react]August 10, 2026· 3 min read

Common React Performance Mistakes You’re Probably Making in Code Reviews

A no‑fluff guide to the most frequent React performance pitfalls seen in code reviews, with practical fixes and real‑world examples.

#performance#react#memoization#lists

Skipping memoization for expensive calculations

It’s tempting to drop a useEffect or just compute a value inline. When that computation touches large arrays or objects, React will re‑run it on every render, killing frame rates.

function ItemList({items}) {
  // Bad: runs on every render
  const total = items.reduce((sum, i) => sum + i.price, 0);
  return <div>Total: {total}</div>;
}

Wrap the heavy work in useMemo and list the dependencies correctly.

function ItemList({items}) {
  const total = useMemo(() =>
    items.reduce((sum, i) => sum + i.price, 0),
    [items]
  );
  return <div>Total: {total}</div>;
}

Unnecessary re‑renders caused by object/array props

Passing a freshly created object or array as a prop forces child components to think the reference changed, even if the contents are identical.

function Parent({data}) {
  return <Child config={{theme: data.theme}} />; // new object each render
}

Lift the constant out of the render or memoize it.

const memoConfig = useMemo(() => ({theme: data.theme}), [data.theme]);
return <Child config={memoConfig} />;

Overusing React.memo without proper prop checks

Many teams slap React.memo on every component hoping for a win. If the component receives new object props every time, the memoization is useless and adds an extra shallow compare.

Instead, audit the component: does it actually receive stable primitives? If not, either memoize the props or drop React.memo.

Heavy CSS-in-JS at the top level

Libraries like styled‑components generate a new class string on each render. When you place them in a layout component that re‑renders often, you end up with thousands of style injections per second.

Extract static styles to a separate file or use the as prop with a pre‑generated class name.

Ignoring the cost of large lists

Rendering 1,000 rows in a table sounds fine until the UI stalls on scroll. The fix is simple: virtualize.

import {FixedSizeList as List} from 'react-window';
function LargeTable({rows}) {
  return (
    <List height={500} itemCount={rows.length} itemSize={35}>
      {({index, style}) => (
        <div style={style}>Row {rows[index].id}</div>
      )}
    </List>
  );
}

Virtualization reduces DOM nodes to only what’s visible, cutting paint time dramatically.

Conclusion

Performance in React isn’t about sprinkling useMemo everywhere; it’s about identifying real work that repeats and breaking the render chain where it hurts. During code reviews, ask yourself: Is this value cheap to compute? Are the props stable? Do we need this many DOM nodes? Answering those three questions will catch most of the mistakes that slip through.

// related

find me in:
linkedin
X
facebook