
1. Avoid Unnecessary Re-renders
React's render cycle is one of the biggest performance costs. Prevent wasteful re-renders by:
- Wrapping components with
React.memo - Using
useCallbackanduseMemoto memoize props and computations - Keeping your props shallow and focused
const ExpensiveComponent = React.memo(({ data }) => {
return <div>{data.title}</div>;
});2. Split Your Bundles
Why load everything upfront?
- Use dynamic imports with
React.lazyandSuspense - Split vendors and shared chunks using Webpack
const LazySettings = React.lazy(() => import('./Settings'));
3. Co-locate and Scope State
Global state is powerful — but overuse can cause unwanted re-renders.
Tips:
- Use local state (
useState) when possible - Use context selectors (
zustand,jotai, oruse-context-selector) - Avoid passing global state deep into component trees
4. Optimize Images and Static Assets
- Use modern formats like WebP, AVIF
- Lazy-load large images
- Compress SVGs
- Use
loading="lazy"for below-the-fold content
<img src="/banner.webp" loading="lazy" alt="Banner" />5. Use Throttling & Debouncing Wisely
Expensive operations like scroll, resize, or map updates should be throttled:
const throttled = useRef(_.throttle(handleScroll, 200));
6. Prefer For Loops Over Higher-Order Functions in Hot Paths
While JavaScript’s .map(), .filter(), and .reduce() methods offer clean and expressive syntax, they introduce overhead in performance-critical code — especially in rendering-heavy React apps or environments like Electron.
❌ Example (more expressive, but slower in large arrays):
const ids = logs.filter(log => log.active).map(log => log.id);✅ Example (faster and more memory-efficient):
const ids = [];
for (const log of logs) {
if (log.active) ids.push(log.id);
}Why it matters:
- Avoids extra array allocations
- Reduces closure and function call overhead
- Runs faster in tight loops or large datasets
- Easier for V8 (Chrome’s JS engine) to optimize
🧪 Real-World Benefit
In one of my Electron apps processing 10k+ map features:
- Using
.map()+.filter()took ~15–20ms - Switching to
forloops brought it down to ~4–6ms - Resulted in smoother user interactions and lower memory usage
When to use for loops:
- Inside render-intensive or animation frames
- During transformation of large data arrays (GeoJSON, logs, telemetry)
- In memory-constrained apps or embedded devices
Conclusion
React performance isn't about one magic fix — it's a mindset. Start by measuring, then optimize carefully and iteratively. Many of these tips are simple yet effective, and they can dramatically improve the user experience.