React Memoization
Optimize your React components with memoization techniques
🚀 What is React Memoization?
Memoization is a performance optimization technique that caches component results to prevent unnecessary re-renders. It helps React apps run faster by remembering previous computations and reusing them when inputs haven't changed.
import React, { memo } from 'react';
// Memoized component - only re-renders when props change
const ExpensiveComponent = memo(({ data }) => {
return <div>{data}</div>;
});
Result:
Component only re-renders when 'data' prop changes, not when parent re-renders.
Memoization Techniques
React.memo()
Memoizes entire components
const MyComponent = memo((props) => {
return <div>{props.name}</div>;
});
useMemo()
Memoizes computed values
const result = useMemo(() => {
return expensiveCalculation(a, b);
}, [a, b]);
useCallback()
Memoizes function references
const handleClick = useCallback(() => {
doSomething(a, b);
}, [a, b]);
Performance
Reduces unnecessary renders
// Prevents child re-renders
<MemoizedChild data={data} />
🔹 Using React.memo()
React.memo() is a higher-order component that prevents re-renders when props haven't changed. It's perfect for components that render often with the same props.
import React, { memo, useState } from 'react';
// Without memo - re-renders every time parent updates
const RegularChild = ({ name }) => {
console.log('RegularChild rendered');
return <div>Hello {name}</div>;
};
// With memo - only re-renders when 'name' changes
const MemoizedChild = memo(({ name }) => {
console.log('MemoizedChild rendered');
return <div>Hello {name}</div>;
});
function Parent() {
const [count, setCount] = useState(0);
const [name, setName] = useState('John');
return (
<div>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
<MemoizedChild name={name} />
</div>
);
}
Output:
MemoizedChild only re-renders when 'name' changes, not when 'count' changes.
🔹 Using useMemo()
useMemo() caches the result of expensive calculations. It only recalculates when dependencies change, saving processing time on every render.
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation() {
const [count, setCount] = useState(0);
const [items, setItems] = useState([1, 2, 3, 4, 5]);
// Without useMemo - calculates on every render
// const total = items.reduce((sum, item) => sum + item, 0);
// With useMemo - only calculates when 'items' changes
const total = useMemo(() => {
console.log('Calculating total...');
return items.reduce((sum, item) => sum + item, 0);
}, [items]);
return (
<div>
<p>Total: {total}</p>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
</div>
);
}
Output:
Total: 15
Calculation only runs when 'items' array changes, not on every button click.
🔹 Using useCallback()
useCallback() memoizes function references to prevent child components from re-rendering. It's useful when passing callbacks to optimized child components that rely on reference equality.
import React, { useState, useCallback, memo } from 'react';
const Button = memo(({ onClick, children }) => {
console.log('Button rendered:', children);
return <button onClick={onClick}>{children}</button>;
});
function Parent() {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
// Without useCallback - new function on every render
// const handleClick = () => setCount(count + 1);
// With useCallback - same function reference
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<Button onClick={handleClick}>Increment</Button>
<button onClick={() => setOtherState(otherState + 1)}>
Other: {otherState}
</button>
</div>
);
}
Output:
Memoized Button doesn't re-render when 'otherState' changes.
🔹 When to Use Memoization
Memoization isn't always necessary. Use it strategically for better performance:
✅ Good Use Cases:
- Components that render frequently with same props
- Expensive calculations or data transformations
- Large lists or complex component trees
- Passing callbacks to memoized child components
❌ Avoid When:
- Props change frequently anyway
- Component is already fast
- Simple calculations or small components
- Premature optimization without measuring
// Good: Expensive list filtering
const filteredList = useMemo(() => {
return largeArray.filter(item => item.active);
}, [largeArray]);
// Bad: Simple addition (overhead not worth it)
const sum = useMemo(() => a + b, [a, b]);