Avoiding unnecessary renders helps your app run faster and smoother by not updating parts of the screen when nothing has changed.
Avoiding unnecessary renders in React
const MemoizedComponent = React.memo(Component); const memoizedCallback = React.useCallback(() => { // function code }, [dependencies]); const memoizedValue = React.useMemo(() => computeValue(), [dependencies]);
React.memo wraps a component to skip re-render if props are the same.
useCallback keeps a function the same between renders unless dependencies change.
onClick or label props change.const Button = React.memo(({ onClick, label }) => { console.log('Button rendered'); return <button onClick={onClick}>{label}</button>; });
handleClick is memoized so Button won't re-render just because Parent re-renders.const Parent = () => { const [count, setCount] = React.useState(0); const handleClick = React.useCallback(() => { setCount(c => c + 1); }, []); return <Button onClick={handleClick} label="Click me" />; };
useMemo caches the result of a heavy calculation until input changes.const expensiveValue = React.useMemo(() => { return computeHeavyTask(); }, [input]);
In this example, the Child component only re-renders when the count changes. Typing in the input does not cause Child to re-render because it is wrapped with React.memo. You can see "Child rendered" in the console only when the count changes.
import React from 'react'; const Child = React.memo(({ value }) => { console.log('Child rendered'); return <div>Value: {value}</div>; }); export default function App() { const [count, setCount] = React.useState(0); const [text, setText] = React.useState(''); return ( <div> <button onClick={() => setCount(count + 1)}>Increment Count</button> <input aria-label="Input text" value={text} onChange={e => setText(e.target.value)} placeholder="Type here" /> <Child value={count} /> </div> ); }
Wrapping components with React.memo only works if props are simple and stable.
Use useCallback and useMemo to keep functions and values stable between renders.
Too much memoization can make code complex, so use it only when you notice performance issues.
Avoid unnecessary renders to make your app faster and smoother.
Use React.memo to skip re-rendering components when props don't change.
Use useCallback and useMemo to keep functions and values from changing needlessly.
Practice
React.memo in a React component?Solution
Step 1: Understand React.memo's role
React.memo is a higher-order component that wraps a functional component to optimize rendering.Step 2: Identify its effect on rendering
It skips re-rendering the wrapped component if its props remain the same, improving performance.Final Answer:
To prevent re-rendering when the component's props have not changed -> Option CQuick Check:
React.memo skips renders if props unchanged = D [OK]
- Thinking React.memo forces re-render
- Confusing React.memo with state updates
- Believing it converts component types
useCallback in React?Solution
Step 1: Recall useCallback syntax
useCallback takes a function and a dependency array, returning a memoized version of the function.Step 2: Check each option's correctness
const memoizedFn = useCallback(() => { doSomething(); }, []); correctly passes a function and an empty dependency array, memoizing the function properly.Final Answer:
const memoizedFn = useCallback(() => { doSomething(); }, []); -> Option AQuick Check:
useCallback needs function and dependencies = C [OK]
- Calling the function inside useCallback instead of passing it
- Omitting the dependency array
- Passing function reference without parentheses incorrectly
const MyComponent = React.memo(({ count, onClick }) => {
console.log('Rendered');
return <button onClick={onClick}>Count: {count}</button>;
});
function App() {
const [count, setCount] = React.useState(0);
const handleClick = () => setCount(count + 1);
return <MyComponent count={count} onClick={handleClick} />;
}What will happen when
App re-renders?Solution
Step 1: Understand React.memo and props
React.memo skips re-render if props are shallowly equal. Here,onClickis a new function each render.Step 2: Analyze function recreation
SincehandleClickis recreated on every render, its reference changes, causing MyComponent to re-render.Final Answer:
MyComponent will re-render every time becausehandleClickis recreated on each render -> Option BQuick Check:
New function prop breaks memo = B [OK]
- Assuming React.memo ignores function prop changes
- Thinking React.memo prevents all re-renders
- Ignoring function identity in props
const Parent = () => {
const [count, setCount] = React.useState(0);
const increment = () => setCount(count + 1);
return <Child onClick={increment} />;
};
const Child = React.memo(({ onClick }) => {
console.log('Child rendered');
return <button onClick={onClick}>Click</button>;
});How can you fix the unnecessary re-renders of
Child?Solution
Step 1: Identify cause of re-renders
Theincrementfunction is recreated on every render, changing its reference and causingChildto re-render.Step 2: Apply useCallback to memoize function
WrappingincrementinuseCallbackwithcountdependency keeps the same function reference unlesscountchanges.Final Answer:
WrapincrementinuseCallbackwithcountas dependency -> Option AQuick Check:
Memoize functions with useCallback to avoid re-renders = A [OK]
- Removing React.memo which disables optimization
- Moving function outside loses access to state
- Using useMemo incorrectly for functions
Solution
Step 1: Understand props causing re-renders
The inline filter function changes reference every render, causing child re-renders despite React.memo.Step 2: Use React.memo and useCallback together
Wrapping child with React.memo and memoizing the filter function with useCallback keeps function reference stable, avoiding unnecessary renders.Final Answer:
Wrap the child component with React.memo and memoize the filter function using useCallback with proper dependencies -> Option DQuick Check:
Memoize functions and use React.memo to optimize renders = A [OK]
- Relying on React.memo without memoizing functions
- Memoizing filtered list inside child instead of function
- Avoiding React.memo and causing extra renders
Ready to prove it?
Pass the test and this pattern moves unknown
