React Performance Overview Dedicated performance optimization skill for React applications. Covers the full spectrum from build-time optimizations (code splitting, barrel file avoidance) through runtime techniques (memoization, transitions, content-visibility) to diagnostic tooling (React DevTools Profiler, bundle analyzers). When to use: Reducing Time to Interactive, shrinking bundle size, eliminating re-renders, profiling slow components, optimizing large lists, lazy loading heavy dependencies, auditing React app performance. When NOT to use: General React component patterns (use skill), fr…

: 'react-dom/profiling',\n 'scheduler/tracing': 'scheduler/tracing-profiling',\n },\n },\n});\n```\n\nBuild and serve the production bundle, then profile with React DevTools.\n\n## Bundle Analysis\n\nVisualize what is in your JavaScript bundles to find optimization targets.\n\n### Next.js Bundle Analyzer\n\n```bash\npnpm add -D @next/bundle-analyzer\n```\n\n```js\n// next.config.js\nconst withBundleAnalyzer = require('@next/bundle-analyzer')({\n enabled: process.env.ANALYZE === 'true',\n});\n\nmodule.exports = withBundleAnalyzer({});\n```\n\n```bash\nANALYZE=true next build\n```\n\nOpens an interactive treemap showing chunk composition. Look for:\n\n- Unexpectedly large dependencies\n- Duplicate packages (multiple versions)\n- Libraries that should be code-split\n\n### Vite Bundle Analysis\n\n```bash\npnpm add -D rollup-plugin-visualizer\n```\n\n```ts\n// vite.config.ts\nimport { visualizer } from 'rollup-plugin-visualizer';\n\nexport default defineConfig({\n plugins: [visualizer({ open: true, gzipSize: true })],\n});\n```\n\n### Source Map Explorer\n\nFramework-agnostic tool that works with any source maps:\n\n```bash\nnpx source-map-explorer dist/assets/*.js\n```\n\n## Performance Measurement in Code\n\nUse the React Profiler component for programmatic performance tracking:\n\n```tsx\nimport { Profiler, type ProfilerOnRenderCallback } from 'react';\n\nconst onRender: ProfilerOnRenderCallback = (\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n) => {\n if (actualDuration > 16) {\n console.warn(`Slow render: ${id} took ${actualDuration.toFixed(1)}ms`);\n }\n};\n\nfunction App() {\n return (\n \u003cProfiler id=\"Dashboard\" onRender={onRender}>\n \u003cDashboard />\n \u003c/Profiler>\n );\n}\n```\n\nThe 16ms threshold corresponds to 60fps. Components exceeding this cause visible jank.\n\n## Common Bottleneck Patterns\n\n### Large List Without Virtualization\n\nRendering thousands of DOM nodes causes slow initial render and expensive re-renders:\n\n```tsx\nimport { useVirtualizer } from '@tanstack/react-virtual';\n\nfunction VirtualList({ items }: { items: Item[] }) {\n const parentRef = useRef\u003cHTMLDivElement>(null);\n\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 50,\n });\n\n return (\n \u003cdiv ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>\n \u003cdiv\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n position: 'relative',\n }}\n >\n {virtualizer.getVirtualItems().map((virtualItem) => (\n \u003cdiv\n key={virtualItem.key}\n style={{\n position: 'absolute',\n top: 0,\n transform: `translateY(${virtualItem.start}px)`,\n height: `${virtualItem.size}px`,\n width: '100%',\n }}\n >\n \u003cItemRow item={items[virtualItem.index]} />\n \u003c/div>\n ))}\n \u003c/div>\n \u003c/div>\n );\n}\n```\n\nVirtualization renders only visible items. For 10,000 items, only ~20 DOM nodes exist at any time.\n\n### Context Re-render Cascade\n\nA single context value change re-renders all consumers:\n\n```tsx\nconst ThemeContext = createContext\u003cTheme>(defaultTheme);\nconst UserContext = createContext\u003cUser | null>(null);\n\nfunction AppProviders({ children }: { children: React.ReactNode }) {\n const [theme, setTheme] = useState\u003cTheme>(defaultTheme);\n const [user, setUser] = useState\u003cUser | null>(null);\n\n return (\n \u003cThemeContext.Provider value={theme}>\n \u003cUserContext.Provider value={user}>{children}\u003c/UserContext.Provider>\n \u003c/ThemeContext.Provider>\n );\n}\n```\n\nSplit contexts by update frequency. Components consuming `ThemeContext` do not re-render when `user` changes.\n\n### Expensive Render in Unrelated Update\n\nState colocation prevents unrelated components from re-rendering:\n\n```tsx\nfunction SearchSection() {\n const [query, setQuery] = useState('');\n const [results, setResults] = useState\u003cResult[]>([]);\n\n return (\n \u003cdiv>\n \u003cSearchInput query={query} onChange={setQuery} />\n \u003cSearchResults results={results} />\n \u003c/div>\n );\n}\n\nfunction Page() {\n return (\n \u003cdiv>\n \u003cSearchSection />\n \u003cExpensiveChart />\n \u003c/div>\n );\n}\n```\n\nBy colocating `query` state inside `SearchSection`, typing in the search input does not re-render `ExpensiveChart`.\n\n## Optimization Priority\n\nWhen optimizing a React application, prioritize by impact:\n\n1. **Eliminate data fetching waterfalls** -- parallel fetches, Suspense streaming (CRITICAL)\n2. **Reduce bundle size** -- code splitting, direct imports, deferred third-party (CRITICAL)\n3. **Fix re-render cascades** -- context splitting, state colocation, memoization (MEDIUM)\n4. **Optimize rendering** -- virtualization, content-visibility, transitions (MEDIUM)\n5. **JavaScript micro-optimizations** -- loop combining, Set/Map lookups (LOW)\n\nStart from the top. Lower-priority optimizations rarely matter if higher-priority issues exist.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8382,"content_sha256":"c35df57e36966e5b8562d3040cff47b0aef7962e2b06e9e2b190a605205e288c"},{"filename":"references/rendering-optimization.md","content":"---\ntitle: Rendering Optimization\ndescription: React.memo, useMemo, useCallback targeting, React Compiler automatic memoization, re-render elimination patterns, startTransition, and state management for performance\ntags:\n [\n memo,\n useMemo,\n useCallback,\n compiler,\n re-renders,\n startTransition,\n derived-state,\n functional-setState,\n ]\n---\n\n# Rendering Optimization\n\n## React Compiler (Preferred)\n\nReact Compiler automatically applies memoization equivalent to `useMemo`, `useCallback`, and `React.memo` at build time. Code that follows the Rules of React gets optimized without manual intervention.\n\nWhen the compiler is enabled, remove manual memoization unless the compiler explicitly skips a component (check React DevTools for the \"Memo\" badge).\n\n```tsx\nfunction ExpensiveComponent({ data, onClick }: Props) {\n const processedData = expensiveProcessing(data);\n\n const handleClick = (item: Item) => {\n onClick(item.id);\n };\n\n return (\n \u003cdiv>\n {processedData.map((item) => (\n \u003cItem key={item.id} onClick={() => handleClick(item)} />\n ))}\n \u003c/div>\n );\n}\n```\n\nThe compiler optimizes this automatically. No `useMemo`, `useCallback`, or `memo` needed.\n\n## When to Use Manual Memoization\n\nWithout React Compiler, or when the compiler skips a component, apply memoization selectively.\n\n### React.memo -- Component-Level Memoization\n\nWrap components that receive stable props from frequently re-rendering parents:\n\n```tsx\nconst UserAvatar = memo(function UserAvatar({ user }: { user: User }) {\n const id = useMemo(() => computeAvatarId(user), [user]);\n return \u003cAvatar id={id} />;\n});\n\nfunction Profile({ user, loading }: Props) {\n if (loading) return \u003cSkeleton />;\n return (\n \u003cdiv>\n \u003cUserAvatar user={user} />\n \u003c/div>\n );\n}\n```\n\nExtracting into a memoized component enables early returns before expensive computation.\n\n### useMemo -- Expensive Computations Only\n\n```tsx\nconst doubled = value * 2;\n\nconst sortedItems = useMemo(\n () => items.toSorted((a, b) => a.price - b.price),\n [items],\n);\n\nconst selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]);\n```\n\nSkip `useMemo` for cheap operations (arithmetic, string concatenation). Use it for sorting, filtering, or building lookup structures from arrays.\n\n### useCallback -- Memoized Child Consumers Only\n\n```tsx\nconst handleClick = useCallback(() => doSomething(id), [id]);\nreturn \u003cMemoizedChild onClick={handleClick} />;\n```\n\nSkip `useCallback` when the consumer is not memoized -- the overhead exceeds the benefit.\n\n## Functional setState for Stable Callbacks\n\nUse the functional update form to eliminate state dependencies from callbacks:\n\n```tsx\nfunction TodoList() {\n const [items, setItems] = useState(initialItems);\n\n const addItems = useCallback((newItems: Item[]) => {\n setItems((curr) => [...curr, ...newItems]);\n }, []);\n\n const removeItem = useCallback((id: string) => {\n setItems((curr) => curr.filter((item) => item.id !== id));\n }, []);\n\n return \u003cItemsEditor items={items} onAdd={addItems} onRemove={removeItem} />;\n}\n```\n\nCallbacks with empty dependency arrays are never recreated, preventing unnecessary child re-renders.\n\n## Defer State Reads\n\nAvoid subscribing to dynamic state that is only used inside callbacks:\n\n```tsx\nfunction ShareButton({ chatId }: { chatId: string }) {\n const handleShare = () => {\n const params = new URLSearchParams(window.location.search);\n const ref = params.get('ref');\n shareChat(chatId, { ref });\n };\n\n return \u003cbutton onClick={handleShare}>Share\u003c/button>;\n}\n```\n\nReading `searchParams` on demand instead of via `useSearchParams()` avoids re-renders when URL changes.\n\n## Subscribe to Derived State\n\nSubscribe to derived booleans instead of continuous values:\n\n```tsx\nfunction Sidebar() {\n const isMobile = useMediaQuery('(max-width: 767px)');\n return \u003cnav className={isMobile ? 'mobile' : 'desktop'} />;\n}\n```\n\nThis re-renders only when the boolean changes, not on every pixel of window resize.\n\n## Derive State During Render\n\nCompute derived values during render instead of syncing with effects:\n\n```tsx\nfunction FilteredList({ items, filter }: Props) {\n const filtered = items.filter((item) => item.category === filter);\n\n return (\n \u003cul>\n {filtered.map((item) => (\n \u003cli key={item.id}>{item.name}\u003c/li>\n ))}\n \u003c/ul>\n );\n}\n```\n\nUsing `useEffect` to sync derived state adds an extra render cycle and is unnecessary.\n\n## startTransition for Non-Urgent Updates\n\nMark frequent, non-urgent state updates as transitions to keep the UI responsive:\n\n```tsx\nimport { startTransition } from 'react';\n\nfunction SearchPage() {\n const [query, setQuery] = useState('');\n const [results, setResults] = useState\u003cResult[]>([]);\n\n const handleChange = (value: string) => {\n setQuery(value);\n startTransition(() => {\n setResults(search(value));\n });\n };\n\n return (\n \u003c>\n \u003cinput value={query} onChange={(e) => handleChange(e.target.value)} />\n \u003cResultsList results={results} />\n \u003c/>\n );\n}\n```\n\nThe input stays responsive while search results update in the background.\n\n## Stable Object References\n\nAvoid creating new object or array literals as props on every render:\n\n```tsx\nconst style = { color: 'red' };\n\nfunction Parent() {\n return \u003cChild style={style} />;\n}\n```\n\nFor dynamic values, use `useMemo`:\n\n```tsx\nfunction Parent({ color }: { color: string }) {\n const style = useMemo(() => ({ color }), [color]);\n return \u003cMemoizedChild style={style} />;\n}\n```\n\n## content-visibility for Long Lists\n\nUse CSS `content-visibility` to skip layout and paint for off-screen items:\n\n```css\n.list-item {\n content-visibility: auto;\n contain-intrinsic-size: 0 80px;\n}\n```\n\n```tsx\nfunction MessageList({ messages }: { messages: Message[] }) {\n return (\n \u003cdiv className=\"overflow-y-auto h-screen\">\n {messages.map((msg) => (\n \u003cdiv key={msg.id} className=\"list-item\">\n \u003cAvatar user={msg.author} />\n \u003cdiv>{msg.content}\u003c/div>\n \u003c/div>\n ))}\n \u003c/div>\n );\n}\n```\n\nFor 1000 items, the browser skips layout/paint for ~990 off-screen items.\n\n## Hoist Static JSX\n\nExtract constant JSX elements outside component functions to avoid recreation:\n\n```tsx\nconst emptyState = \u003cdiv className=\"empty\">No items found\u003c/div>;\n\nfunction ItemList({ items }: { items: Item[] }) {\n if (items.length === 0) return emptyState;\n return (\n \u003cul>\n {items.map((item) => (\n \u003cli key={item.id}>{item.name}\u003c/li>\n ))}\n \u003c/ul>\n );\n}\n```\n\nStatic JSX hoisted outside the component is created once and reused across renders.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6596,"content_sha256":"91aafab1c65bc3bb6709dd8528c9d6b9348a8c10848a4f4f919b640625da4215"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"React Performance","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"Dedicated performance optimization skill for React applications. Covers the full spectrum from build-time optimizations (code splitting, barrel file avoidance) through runtime techniques (memoization, transitions, content-visibility) to diagnostic tooling (React DevTools Profiler, bundle analyzers).","type":"text"}]},{"type":"paragraph","content":[{"text":"When to use:","type":"text","marks":[{"type":"strong"}]},{"text":" Reducing Time to Interactive, shrinking bundle size, eliminating re-renders, profiling slow components, optimizing large lists, lazy loading heavy dependencies, auditing React app performance.","type":"text"}]},{"type":"paragraph","content":[{"text":"When NOT to use:","type":"text","marks":[{"type":"strong"}]},{"text":" General React component patterns (use ","type":"text"},{"text":"react-patterns","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill), framework-specific optimizations like Next.js caching (use framework skill), non-React performance (network, database, CDN).","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Reference","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Category","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Technique","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Key Points","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Compiler","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React Compiler","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Automatic memoization at build time; eliminates manual memo/useMemo/useCallback","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Memoization","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React.memo(Component)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Wrap components receiving stable primitive props from frequently re-rendering parents","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Memoization","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"useMemo(fn, deps)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Expensive computations only: sorting, filtering, Set/Map construction","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Memoization","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"useCallback(fn, deps)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Only when passed to memoized children; use functional setState for stable refs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Splitting","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React.lazy(() => import())","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lazy-load heavy components with ","type":"text"},{"text":"\u003cSuspense>","type":"text","marks":[{"type":"code_inline"}]},{"text":" fallback","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Splitting","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Preload on intent","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trigger ","type":"text"},{"text":"import()","type":"text","marks":[{"type":"code_inline"}]},{"text":" on hover/focus for perceived speed","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bundle","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Direct imports","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Avoid barrel files; import from specific paths to reduce module count","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bundle","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Defer third-party","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Load analytics, logging after hydration","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-renders","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"startTransition","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mark non-urgent updates (search, scroll tracking) as interruptible","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-renders","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Functional setState","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"setState(prev => ...)","type":"text","marks":[{"type":"code_inline"}]},{"text":" eliminates state dependencies from callbacks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-renders","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Derived state","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Subscribe to booleans, not continuous values; compute during render","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-renders","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Defer state reads","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Read dynamic state (searchParams) inside callbacks, not at render","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rendering","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"content-visibility: auto","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skip layout/paint for off-screen items in long lists","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rendering","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hoist static JSX","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Extract constant elements outside component functions","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Profiling","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React DevTools Profiler","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Record renders, identify slow components, flamegraph analysis","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Profiling","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bundle analyzer","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Visualize chunk sizes, find oversized dependencies","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common Mistakes","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mistake","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Correct Pattern","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Wrapping everything in useMemo/useCallback","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trust React Compiler first; only memoize expensive computations or memoized-child callbacks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Memoizing cheap operations like ","type":"text"},{"text":"value * 2","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skip memo for simple primitives; overhead exceeds recomputation cost","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Importing from barrel files (","type":"text"},{"text":"lucide-react","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"@mui/material","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Import directly from specific paths or use ","type":"text"},{"text":"optimizePackageImports","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Loading analytics/tracking in the initial bundle","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Defer with lazy + mounted state to load after hydration","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Subscribing to continuous values (window width) for boolean checks","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"useMediaQuery","type":"text","marks":[{"type":"code_inline"}]},{"text":" or derived boolean to re-render only on threshold change","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Referencing state in useCallback dependency array","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use functional setState ","type":"text"},{"text":"setState(prev => ...)","type":"text","marks":[{"type":"code_inline"}]},{"text":" for stable callbacks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Using ","type":"text"},{"text":"useEffect","type":"text","marks":[{"type":"code_inline"}]},{"text":" to derive state from props","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Compute derived values during render; effects add an extra render cycle","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Creating new object literals as props on every render","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hoist static objects outside component; use useMemo for dynamic objects","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Profiling in development mode","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Always profile production builds; dev mode includes extra warnings that skew results","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Delegation","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Profile and diagnose performance bottlenecks","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"Explore","type":"text","marks":[{"type":"code_inline"}]},{"text":" agent to run React DevTools Profiler, analyze bundle composition, and trace re-render cascades","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Apply performance optimizations to existing code","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"Task","type":"text","marks":[{"type":"code_inline"}]},{"text":" agent to implement code splitting, add memoization boundaries, and optimize rendering","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Plan performance improvement strategy","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"Plan","type":"text","marks":[{"type":"code_inline"}]},{"text":" agent to prioritize optimizations by impact (waterfalls > bundle > re-renders) and create an optimization roadmap","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If the ","type":"text"},{"text":"react-patterns","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill is available, delegate general component architecture and React 19 API questions to it. Otherwise, recommend: ","type":"text"},{"text":"npx skills add oakoss/agent-skills --skill react-patterns","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rendering optimization: memo, useMemo, useCallback, compiler, re-render elimination","type":"text","marks":[{"type":"link","attrs":{"href":"references/rendering-optimization.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Code splitting: React.lazy, Suspense, dynamic imports, bundle optimization","type":"text","marks":[{"type":"link","attrs":{"href":"references/code-splitting.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Profiling and debugging: DevTools, performance measurement, common bottlenecks","type":"text","marks":[{"type":"link","attrs":{"href":"references/profiling-and-debugging.md","title":null}}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"react-performance","author":"@skillopedia","source":{"stars":12,"repo_name":"agent-skills","origin_url":"https://github.com/oakoss/agent-skills/blob/HEAD/skills/react-performance/SKILL.md","repo_owner":"oakoss","body_sha256":"4215540824a803207f39c026a815d8bed7b221e9f707dc8cd0a3478a1016fb1f","cluster_key":"434c644226199b0de3eb3344bc94bb673132a071f70cc2d932e18adc4def626b","clean_bundle":{"format":"clean-skill-bundle-v1","source":"oakoss/agent-skills/skills/react-performance/SKILL.md","attachments":[{"id":"e9e782ff-d903-5508-83c4-a8ce32e13bfb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e9e782ff-d903-5508-83c4-a8ce32e13bfb/attachment.md","path":"references/code-splitting.md","size":5872,"sha256":"5eb9134afa6e708be34c5ec964abb3dc747d84bf8970039ba0c9a52f23fc7474","contentType":"text/markdown; charset=utf-8"},{"id":"41dba982-5799-5efe-a2a3-cb6867a7b8f1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/41dba982-5799-5efe-a2a3-cb6867a7b8f1/attachment.md","path":"references/profiling-and-debugging.md","size":8382,"sha256":"c35df57e36966e5b8562d3040cff47b0aef7962e2b06e9e2b190a605205e288c","contentType":"text/markdown; charset=utf-8"},{"id":"488a426b-b716-56e8-b35d-f2a730ebb21a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/488a426b-b716-56e8-b35d-f2a730ebb21a/attachment.md","path":"references/rendering-optimization.md","size":6596,"sha256":"91aafab1c65bc3bb6709dd8528c9d6b9348a8c10848a4f4f919b640625da4215","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"0d426b2f625aadf39230b835119921935d8d3981a48406233101fdb3dd68e457","attachment_count":3,"text_attachments":3,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/react-performance/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"security","category_label":"Security"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"v1","category":"security","metadata":{"author":"oakoss","source":"https://react.dev/learn/react-compiler","version":"1.0"},"import_tag":"clean-skills-v1","description":"React performance optimization patterns including memoization, code splitting, bundle size reduction, re-render elimination, and profiling. Covers React Compiler automatic optimization, manual memo/useMemo/useCallback targeting, React.lazy with Suspense, barrel file avoidance, content-visibility for large lists, startTransition for non-urgent updates, and React DevTools profiling.\n\nUse when optimizing React app performance, reducing bundle size, eliminating unnecessary re-renders, debugging slow components, code splitting, or profiling rendering bottlenecks. Use for performance audit, bundle analysis, re-render diagnosis, lazy loading, virtualization.\n","user-invocable":false}},"renderedAt":1782986214958}

React Performance Overview Dedicated performance optimization skill for React applications. Covers the full spectrum from build-time optimizations (code splitting, barrel file avoidance) through runtime techniques (memoization, transitions, content-visibility) to diagnostic tooling (React DevTools Profiler, bundle analyzers). When to use: Reducing Time to Interactive, shrinking bundle size, eliminating re-renders, profiling slow components, optimizing large lists, lazy loading heavy dependencies, auditing React app performance. When NOT to use: General React component patterns (use skill), fr…