React Rendering Lifecycle and How Re-renders Can Be Optimised

Rohit Sonar Blogs
Rohit Sonar
Cover Image of the article

When you work with React, one of the most important things to understand is its rendering lifecycle. Knowing how and when components render and re-render is key to writing applications that are not only correct but also performant and scalable.

Let’s break this down.

1. The React Rendering Lifecycle

At a high level, React components go through three main stages:

  1. Initial Render
    • When a component is mounted for the first time, React builds the UI from scratch.
    • It reconciles the component’s JSX with the DOM and commits it to the screen.
  2. Re-render (Updates)
    • A component re-renders when its state or props change.
    • React uses its Virtual DOM diffing algorithm to figure out what changed and updates only the necessary parts of the real DOM.
  3. Unmount
    • When a component is removed, React cleans up resources like event listeners or effects to free memory.

2. Why Do Re-renders Matter?

Re-renders are natural they’re how React stays reactive.
But unnecessary re-renders can lead to:

  • Slow UIs (laggy scrolling, delayed responses).
  • Wasted resources (CPU cycles for DOM diffing and painting).
  • Lower scalability (especially in apps with hundreds of components).

In short: Re-renders are good when needed, costly when excessive.

3. Common Causes of Excessive Re-renders

  • Passing new object/array references as props (e.g., props={{}} in JSX).
  • Unnecessary state updates (calling setState with the same value).
  • Re-render chains where a parent update triggers child updates.
  • Inline functions inside JSX that recreate on every render.

4. Optimizing React Re-renders

Here are practical strategies:

4.1 Memoization of Components

Use React.memo to prevent child components from re-rendering unless their props change.

const Child = React.memo(({ value }) => {
console.log("Rendered");
return <div>{value}</div>;
});

4.2 Stabilizing Functions with useCallback

Inline functions re-create on every render. Use useCallback to memoize them.

const handleClick = useCallback(() => {
console.log("Clicked");
}, []);

4.3 Avoid Unnecessary State

Not everything belongs in useState. Derive values from props or compute them directly when possible.

4.4 Memoizing Expensive Computations with useMemo

const sortedList = useMemo(() => expensiveSort(data), [data]);

4.5 Split Large Components

Break down complex components so React re-renders only the parts that need updating.

4.6 Virtualization for Large Lists

For thousands of items, use libraries like react-window or react-virtualized to render only what’s visible.

5. Mental Model for Re-renders

Think of React rendering like this:

  • State/Props change → React re-renders the component.
  • Virtual DOM diffing → Finds changes.
  • DOM update → Applies only what’s necessary.

Your job as a developer?
👉 Minimize how often and how much React needs to re-render.

Conclusion

React’s rendering lifecycle is designed for efficiency, but careless coding can still lead to unnecessary re-renders. By memoizing, stabilizing references, deriving state smartly, and splitting components, you can keep your apps fast and scalable.

The golden rule: Don’t prematurely optimize every render. Measure with tools like React DevTools Profiler, identify real bottlenecks, and then apply these strategies.
Happy Coding!