React
The Complete React Performance Guide: From Slow to Sub-Second
A practical, no-fluff walkthrough of the React performance techniques that actually move the needle — memoisation, code-splitting, virtualisation, and the profiling workflow to find real bottlenecks.
Most "React is slow" complaints aren't about React — they're about an app that re-renders far more than it needs to, ships more JavaScript than it uses, and never got profiled before shipping. Here's the order of operations that actually fixes it.
1. Profile before you optimise anything
The React DevTools Profiler tab is the starting point, not npm packages. Record an interaction, look at which components re-rendered and why, and resist the urge to wrap everything in useMemo pre-emptively. Premature memoisation adds complexity and can be slower than the re-render it prevents.
2. Fix re-renders at the source
- Keep state as local as possible — lifting state up "just in case" causes every consumer to re-render on every change.
- Split context providers by concern instead of one giant context object; a single context update re-renders every consumer regardless of which slice changed.
- Use
React.memoon components that receive stable props and render often, not on every component by default.
3. Code-split by route, then by heavy component
React.lazy combined with Suspense at the route level is the single highest-leverage change for initial load time. After that, look for individually heavy dependencies — chart libraries, rich text editors, PDF viewers — and lazy-load those behind interaction, not on initial mount.
Key takeaway: Run source-map-explorer or the Vite/webpack bundle analyzer before guessing what's heavy. It's almost never what you expect.
4. Virtualise long lists
Rendering 500 DOM nodes for a list the user can only see 10 of at a time is one of the most common real-world bottlenecks. Libraries like react-window or @tanstack/react-virtual render only the visible slice and keep scroll performance smooth regardless of list length.
5. Move expensive computation out of render
Sorting, filtering, and formatting large datasets inside the render function on every keystroke is a common cause of input lag. Debounce the input, memoise the derived data with useMemo, and consider moving genuinely heavy computation (large CSV parsing, image processing) into a Web Worker so it doesn't block the main thread at all.
6. Don't ignore images and fonts
React performance work often stops at the JavaScript layer and ignores the biggest Largest Contentful Paint contributor on most pages: unoptimised images and render-blocking fonts. Serve responsive image sizes, use loading="lazy" below the fold, and preload the font weights you actually use.
The realistic target
For most marketing sites and dashboards, sub-second Time to Interactive on a mid-range mobile device is achievable with the steps above — no rewrite required. The goal isn't a perfect Lighthouse 100; it's removing the two or three bottlenecks that are actually costing you conversions or usability.