React applications can feel fast at the prototype stage and become noticeably slow as they grow. More components, more state, more data, and more re-renders accumulate until interactions that should feel instant have visible lag. Understanding why React re-renders happen and how to prevent unnecessary ones is the foundation of React performance engineering.
This guide covers the profiling approach and the specific optimisation techniques that production React teams use to keep applications performant as they scale.
Profile Before Optimising
Premature React performance optimisation is a real waste of engineering time. Adding useMemo, useCallback, and React.memo everywhere without profiling first adds complexity without necessarily improving performance - and can actually hurt performance in some cases by adding overhead for optimisations that were not needed.
The React DevTools Profiler is the essential tool. It shows which components render, how long each render takes, and what triggered the render. Before any optimisation work:
- Reproduce the performance problem in a profiled session
- Identify which components are rendering most frequently or taking the longest
- Determine why each is rendering - what state or prop changed?
- Decide whether the render is necessary (the component's output actually changed) or unnecessary (the component re-renders but produces the same output)
Optimise the components that profile data identifies as the actual bottlenecks. Ignore the rest.
Understanding Re-Renders
React re-renders a component when its state changes, its props change (by reference, not value), its parent re-renders (and the component is not memoised), or the context it consumes changes. Most React performance problems are caused by unnecessary re-renders - components re-rendering when their output would be identical.
Memoisation with React.memo, useMemo, and useCallback
React.memo
Wrapping a component in React.memo causes it to skip re-rendering when its props have not changed (by shallow comparison). Effective when a component is expensive to render and its parent re-renders frequently but passes the same props.
Important: React.memo only helps if the props are actually stable between renders. If the parent creates new object or function references on every render, React.memo provides no benefit - the shallow comparison will always see "changed" props.
useCallback
useCallback memoises a function reference, returning the same function reference between renders unless its dependencies change. This matters when passing callback functions as props to React.memo-wrapped components - without useCallback, a new function reference is created on every render, defeating React.memo.
useMemo
useMemo memoises the result of an expensive computation, recalculating only when dependencies change. Use it for: expensive data transformations (filtering or sorting large arrays), derived state calculations that are computationally expensive, and creating stable object references that are passed as props to memoised components.
Do not use useMemo for cheap computations - the memoisation overhead exceeds the computation cost. Profile to identify what is actually expensive before reaching for useMemo.
State Management and Re-Render Scope
Where you put state determines how much of the component tree re-renders when it changes. A common performance problem is state placed too high in the component tree - when it changes, the entire subtree below it re-renders.
State Colocation
Move state as close to where it is used as possible. If only one leaf component uses a piece of state, it should live in that component - not in a parent component that renders many other things. This limits re-renders to the component that actually needs to update.
Context Performance
Every component that consumes a React context re-renders when that context value changes. A context that frequently updates (per-keystroke, per-tick) used by many components causes widespread re-renders. Strategies: split large contexts into smaller, more focused contexts; use context only for values that change infrequently; use specialised state management libraries (Zustand, Jotai) for high-frequency updates.
List Rendering Optimisation
Keys Must Be Stable and Unique
React uses keys to identify list items across renders. Unstable keys (using array index as key) cause React to unmount and remount components when list order changes rather than reusing them. Always use stable, unique identifiers (database IDs, UUID) as list keys.
Virtualisation for Long Lists
Rendering thousands of list items simultaneously creates significant DOM overhead. Virtualisation libraries (react-window, react-virtual, TanStack Virtual) render only the items currently in the viewport plus a buffer, dramatically reducing DOM size and rendering work for long lists. Apply for lists longer than 100-200 items.
Code Splitting and Lazy Loading
Bundling your entire React application into a single JavaScript file means every user downloads code for every route - including routes they never visit. Code splitting with React.lazy and Suspense allows on-demand loading of route components, reducing the initial bundle size and improving Time to Interactive for the main page.
Implement route-level code splitting as a baseline: each major route is a separate bundle, loaded only when the user navigates to it. Component-level code splitting is valuable for large, rarely used components (complex data tables, rich text editors, chart libraries).
Image and Asset Optimisation
- Use appropriately sized images - do not serve a 2000px-wide image to display a 400px thumbnail
- Use next/image or similar for automatic WebP/AVIF format selection, lazy loading, and blur placeholders
- Apply
loading="lazy"to below-the-fold images natively or via framework - Preload critical above-the-fold images with
<link rel="preload">
React Performance at Savyasachi Infotech
At Savyasachi Infotech, React performance engineering is part of our development practice - not an afterthought. We profile, identify bottlenecks, and apply targeted optimisations as part of normal development, and we conduct performance reviews before major releases to catch regressions before users experience them.
If you have a React application with performance problems, or if you want performance built into a new project from the start, talk to our team.
Server Components: The Next Layer of React Performance
React Server Components (available in Next.js App Router) represent a fundamentally different approach to React performance: components that execute on the server and send rendered HTML to the client, with zero client-side JavaScript for the component itself. For components that fetch data and render it without needing interactivity, Server Components eliminate both the JavaScript download cost and the client-side data fetch latency. The performance model is simple: a Server Component's JavaScript never ships to the browser. For content-heavy applications, migrating appropriate components to Server Components can dramatically reduce JavaScript bundle size and improve Core Web Vitals metrics. This is not applicable to all components - interactive components that respond to user events must remain client components - but the principle of pushing the client boundary down the component tree as far as possible is one of the most impactful performance strategies available in modern React.
Is Your React Application Getting Slower as It Grows? Let's Fix That.
React performance problems are diagnosable and fixable with the right profiling approach and targeted optimisation techniques. The key is identifying the actual bottlenecks rather than applying blanket optimisation patterns that add complexity without meaningful improvement.
At Savyasachi Infotech, we profile, diagnose, and optimise React applications for production performance - using React DevTools, Lighthouse, and Web Vitals to identify exactly what is slow and applying targeted fixes that deliver measurable improvements without unnecessary complexity.
Book a free consultation. Share your React performance challenge and we will diagnose the root causes and give you a clear remediation plan.
