React apps can become slow as they grow. This guide covers advanced performance optimization techniques to keep your applications fast and responsive.
Understanding React Performance
Common Bottlenecks
- Unnecessary re-renders
- Large bundle sizes
- Expensive computations in render
- Unoptimized images and assets
- Poor data fetching strategies
Measuring Performance
Use React DevTools Profiler, Chrome DevTools, Lighthouse, and Web Vitals to measure performance.
Rendering Optimization
React.memo()
Prevent re-renders when props have not changed. Wrap expensive components with React.memo().
useMemo() Hook
Memoize expensive calculations. Only recalculate when dependencies change.
useCallback() Hook
Memoize function references to prevent child re-renders.
Key Props
Use stable, unique IDs as keys in lists. Avoid using array indices.
Code Splitting and Lazy Loading
Route-Based Splitting
Split application by routes using React.lazy() and Suspense. Each route loads only when needed.
Component-Based Splitting
Load heavy components like charts or editors only when rendered.
Dynamic Imports
Import large libraries only when needed, like Excel export libraries.
Bundle Size Optimization
Tree Shaking
Import only what you need from libraries. Use individual lodash functions instead of entire library.
Replace Heavy Libraries
- Moment.js (289KB) → date-fns (13KB) or Day.js (7KB)
- Lodash → Individual functions or native JS
- Axios → Fetch API (native)
Analyze Bundle
Use webpack-bundle-analyzer or source-map-explorer to identify large dependencies.
Image Optimization
Modern Formats
- WebP (30% smaller than JPEG)
- AVIF (50% smaller than JPEG)
- SVG for icons and logos
Lazy Loading
Use native loading=lazy attribute or Intersection Observer for custom behavior.
Responsive Images
Serve different sizes based on device screen using picture element.
Data Fetching Optimization
React Query
Use React Query for automatic caching, background refetching, and optimistic updates. Configure staleTime and cacheTime appropriately.
Prefetching
Prefetch data on hover or route change to make navigation instant.
Parallel Queries
Run independent queries in parallel instead of sequentially.
Virtual Lists
Render only visible items for long lists using react-window or react-virtualized. Dramatically improves performance for thousands of items.
State Management
Avoid Prop Drilling
Use Context API or state management library instead of passing props through many levels.
Context Splitting
Split large contexts into smaller ones to prevent unnecessary re-renders.
React 18+ Features
Automatic Batching
React 18 automatically batches multiple state updates in event handlers.
useTransition
Mark expensive updates as non-urgent so they can be interrupted by user input.
useDeferredValue
Defer expensive re-renders while keeping UI responsive.
Common Pitfalls
- Creating new objects/arrays in render
- Inline functions in props
- Large context values
- Missing dependency arrays
- Expensive computations without memoization
Production Build
Use minification, compression, code splitting, and remove console logs in production.
Performance Checklist
- ✅ Use React.memo() for expensive components
- ✅ Implement code splitting at route level
- ✅ Lazy load heavy components
- ✅ Optimize images
- ✅ Use virtual lists for large datasets
- ✅ Implement caching strategy
- ✅ Monitor Core Web Vitals
Conclusion
React performance optimization is an ongoing process. Measure, identify bottlenecks, optimize, and measure again. Focus on user-facing metrics.
Need help optimizing your React application? Our team specializes in React performance optimization. Contact us.
How Direlli can help
Direlli builds high-performance web applications with React and Next.js. Explore our web app development and custom software, or get a free consultation. Direlli is rated 5.0 on Clutch and serves clients across the US, Europe and MENA.