React Component Lifecycle and Rendering Behaviour
Understanding when and why React renders is critical for performance. Here's what senior interviews cover.
When does a component re-render?
A component re-renders when its state changes, its props change, or its parent re-renders.
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
<Child /> {/* re-renders every time Parent re-renders */}
</div>
);
}
function Child() {
console.log('Child renders');
return <p>I'm a child</p>;
}
// Even though Child has no props, it re-renders when Parent does.
// Fix: wrap in React.memo
const Child = React.memo(function Child() {
return <p>I'm a child</p>;
});Lifecycle with useEffect
useEffect maps to the class component lifecycle: componentDidMount, componentDidUpdate, componentWillUnmount.
// componentDidMount equivalent: runs once after mount
useEffect(() => {
initAnalytics();
return () => cleanupAnalytics(); // componentWillUnmount
}, []);
// componentDidUpdate equivalent: runs when deps change
useEffect(() => {
fetchUser(userId);
}, [userId]);
// Runs after every render (both mount and update)
useEffect(() => {
document.title = title;
});Lifting state up
When two components need to share state, move the state to their closest common ancestor.
// WRONG: each component has its own state — they're out of sync
function TemperatureInput({ unit }) {
const [value, setValue] = useState('');
// celsius and fahrenheit inputs can't sync
}
// RIGHT: lift state to the parent
function Calculator() {
const [celsius, setCelsius] = useState('');
const toCelsius = (f) => (f - 32) * 5 / 9;
const toFahrenheit = (c) => c * 9 / 5 + 32;
return (
<>
<Input unit="C" value={celsius}
onChange={setCelsius} />
<Input unit="F" value={toFahrenheit(celsius)}
onChange={c => setCelsius(toCelsius(c))} />
</>
);
}React.memo and preventing unnecessary renders
React.memo wraps a component to skip re-renders if props haven't changed.
// Without memo: re-renders every time parent renders
const ListItem = ({ item, onDelete }) => (
<li>
{item.text}
<button onClick={() => onDelete(item.id)}>Delete</button>
</li>
);
// With memo: only re-renders if item or onDelete reference changes
const ListItem = React.memo(({ item, onDelete }) => (
<li>
{item.text}
<button onClick={() => onDelete(item.id)}>Delete</button>
</li>
));
// IMPORTANT: pair with useCallback to stabilise onDelete reference
const onDelete = useCallback((id) => {
setItems(items => items.filter(i => i.id !== id));
}, []);Exam tip
"What triggers a re-render in React?" is a fundamental interview question. Answer: state change, prop change, or parent re-render. React.memo opts a component out of the third case — but only if props are stable (no new object/function references).
Think you're ready? Prove it.
Take the free React readiness test. Get a score, topic breakdown, and your exact weak areas.
Take the free React test →Free · No sign-up · Instant results