R

React Performance Consultant

Boost productivity using this react, performance, optimization, specialist. Includes structured workflows, validation checks, and reusable patterns for performance testing.

AgentClipticsperformance testingv1.0.0MIT
0 views0 copies

React Performance Consultant

Specialized React optimization agent that diagnoses rendering bottlenecks, reduces bundle sizes, eliminates memory leaks, and improves Core Web Vitals for React applications.

When to Use This Agent

Choose this agent when you need to:

  • Diagnose and fix excessive component re-renders causing janky user interactions
  • Reduce JavaScript bundle size through code splitting, tree shaking, and lazy loading strategies
  • Identify and resolve memory leaks in React component lifecycle and effect hooks
  • Improve Lighthouse performance scores and Core Web Vitals for React-based SPAs

Consider alternatives when:

  • Your performance issues are backend infrastructure bottlenecks unrelated to the React frontend (use the Load Testing Specialist)
  • You need framework-agnostic Core Web Vitals optimization at the HTML/CSS/network level (use the Web Vitals Optimizer Agent)

Quick Start

Configuration

name: react-performance-consultant type: agent category: performance-testing

Example Invocation

claude agent:invoke react-performance-consultant "Analyze Dashboard component tree for unnecessary re-renders and recommend memoization strategy"

Example Output

Performance Audit β€” Dashboard Component Tree
Unnecessary Re-renders Detected: 14 components re-rendering on every state change

Root Cause: Parent <Dashboard> updates `notifications` state, triggering
re-render of all 14 children including <ChartPanel>, <MetricsGrid>, <UserTable>

Recommendations:
1. Wrap <ChartPanel> with React.memo β€” saves ~120ms per interaction
2. Extract notifications into dedicated context to isolate state
3. Replace inline object props with useMemo in <MetricsGrid>
4. Move <UserTable> sort handler to useCallback to stabilize reference

Estimated Impact: Interaction latency reduced from 340ms to 85ms
Bundle Reduction: Lazy-load <ChartPanel> (recharts) β€” saves 147KB gzipped

Core Concepts

React Rendering Pipeline Overview

AspectDetails
Trigger PhaseState change, prop change, context update, or parent re-render initiates reconciliation
Render PhaseReact calls component functions, computes virtual DOM diff (interruptible in concurrent mode)
Commit PhaseReact applies DOM mutations, runs layout effects, then fires passive effects
Optimization LeversReact.memo, useMemo, useCallback, code splitting, virtualization, concurrent features

Optimization Decision Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  React DevTools  │────▢│  Re-render      β”‚
β”‚  Profiler Trace  β”‚     β”‚  Hotspot Map    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                       β”‚
        β–Ό                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Bundle Analyzer │────▢│  Split Point    β”‚
β”‚  (webpack/vite)  β”‚     β”‚  Identification β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                       β”‚
        β–Ό                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Memory Heap     │────▢│  Optimization   β”‚
β”‚  Snapshot Diff   β”‚     β”‚  Action Plan    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration

ParameterTypeDefaultDescription
render_threshold_msinteger16Flag components whose render time exceeds this value (16ms = 60fps budget)
bundle_budget_kbinteger250Maximum gzipped JS bundle size before triggering split recommendations
memo_depthinteger2How many levels deep to analyze prop stability for memoization candidates
track_effectsbooleantrueMonitor useEffect cleanup patterns for potential memory leaks
concurrent_modebooleanfalseEnable analysis of React concurrent features (useTransition, useDeferredValue)

Best Practices

  1. Profile Before Optimizing Premature optimization wastes effort and can make code harder to maintain. Always start with a React DevTools Profiler recording of the actual slow interaction. The flamegraph reveals exactly which components are expensive, letting you target optimizations where they deliver measurable impact.

  2. Stabilize Prop References Before Applying React.memo Wrapping a component in React.memo is useless if its parent passes new object or array references on every render. Use useMemo for computed objects and useCallback for handler functions to ensure referential equality. Otherwise memo performs the comparison work but still re-renders every time.

  3. Code-Split at Route Boundaries First The highest-leverage split points are route-level components because users only load code for the page they visit. Use React.lazy with Suspense at route boundaries before pursuing more granular component-level splits, which add complexity for diminishing returns.

  4. Virtualize Long Lists Instead of Paginating Reactively Rendering thousands of DOM nodes destroys scroll performance regardless of React optimization. Libraries like react-window or TanStack Virtual render only visible items plus a small overscan buffer, keeping DOM node count constant and scroll performance smooth even with massive datasets.

  5. Clean Up Effects and Subscriptions Rigorously Every useEffect that creates a subscription, timer, or event listener must return a cleanup function. Missing cleanups cause memory leaks that accumulate during navigation, eventually degrading performance. Use the React DevTools profiler in strict mode to catch components that mount, unmount, and remount without proper cleanup.

Common Issues

  1. Context updates cause full subtree re-renders A single context provider that holds frequently-changing state (e.g., cursor position, animation frame) forces every consumer in the subtree to re-render. Split contexts by update frequency: put rapidly-changing values in a dedicated context and stable values in another so that most consumers skip unnecessary renders.

  2. Large third-party libraries bloating initial bundle Charting libraries, date pickers, and rich-text editors can add hundreds of kilobytes to the initial load. Import them dynamically with React.lazy or next/dynamic and provide a lightweight placeholder during loading. Check bundle composition with webpack-bundle-analyzer or vite-plugin-visualizer to identify the largest offenders.

  3. Stale closures in memoized callbacks causing incorrect behavior When useCallback captures a stale variable from a previous render, the memoized function operates on outdated data. Ensure the dependency array includes every variable the callback reads. Alternatively, use a ref to hold the latest value and read from the ref inside the callback, which avoids invalidating the memoization.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates