Unnecessary re-renders in React happen when components update without any real change in output. Optimizing these renders improves performance, responsiveness, and user experience.
React re-renders components whenever state or props change. While this is by design, too many unnecessary re-renders can degrade performance, especially in large applications.
In this section, we’ll explore how to identify and avoid unwanted renders for smoother, faster React apps.
// Logs each time the component renders
function Item({ name }) {
console.log(`Rendered: ${name}`);
return <li>{name}</li>;
}
// Prevents re-render unless props change
const Product = React.memo(function Product({ name, price }) {
console.log("Product rendered");
return <p>{name}: ${price}</p>;
});
// Memoizes function reference
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
// Memoizes expensive computation
const filteredData = useMemo(() => data.filter(item => item.active), [data]);
// Inline object causes re-render
<Child options={{ theme: "dark" }} />
// Memoized object prevents re-render
const options = useMemo(() => ({ theme: "dark" }), []);
<Child options={options} />
// Parent component with memoized callback
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(p => p + 1), []);
return (
<div>
<button onClick={increment}>Increment</button>
<Child />
</div>
);
}
// Child wrapped with React.memo
const Child = React.memo(() => {
console.log("Child rendered");
return <p>No unnecessary re-render</p>;
});
Click the button below to update the Parent's state. Watch how the Memoized Child stays static (saved processing) while the Regular Child re-renders unnecessarily.