Install
openclaw skills install @charlie-morrison/react-component-auditorAudit React components for performance, accessibility, hook correctness, prop design, and re-render optimization — identify memo opportunities and state management issues.
openclaw skills install @charlie-morrison/react-component-auditorAudit React components for performance bottlenecks, accessibility issues, hook correctness, prop design problems, and unnecessary re-renders. Identifies memo opportunities, stale closure bugs, and state management anti-patterns.
"Audit my React components for performance"
"Check for unnecessary re-renders"
"Review hook usage in my components"
"Audit accessibility of my React app"
find src -name "*.tsx" -o -name "*.jsx" | head -30
grep -rn "export.*function\|export default\|React.FC\|React.memo" src/components/ | head -30
Re-render detection:
React.memo that receive object/array propsuseCallback on event handlers passed as propsuseMemo on expensive computationsBundle impact:
useEffect with missing dependencies (stale closure bugs)useEffect with too many dependencies (runs too often)useEffect without cleanup (memory leaks on timers, subscriptions)useState for derived state (should be computed)useRef for values that should be useState (no re-render)aria-label on icon buttonsalt textisNotVisible)## React Component Audit
**Components:** 45 | **Custom Hooks:** 12
### 🔴 Critical (3)
1. **Stale closure in useEffect** — UserProfile.tsx:34
`userId` in dependency array but `fetchUser` captures stale `token`
→ Add `token` to deps or use `useCallback` for `fetchUser`
2. **Context re-render storm** — AppProvider.tsx
Single context with 12 values — any change re-renders all consumers
→ Split into AuthContext, ThemeContext, UserContext
3. **Missing keyboard support** — DropdownMenu.tsx
Custom dropdown has no keyboard navigation (Enter, Escape, Arrow keys)
→ Add onKeyDown handler with aria-expanded
### 🟡 Improvements (5)
4. 8 components could benefit from React.memo (receive stable parents)
5. Inline arrow functions in 12 onClick handlers
6. 3 useEffects with empty cleanup (timer, subscription leaks)
7. DashboardPage has 23 props — split into sub-components
8. Form inputs missing htmlFor/id label association in 5 forms
### ✅ Good Practices
- Custom hooks for data fetching with loading/error states
- Proper Suspense boundaries with fallbacks
- Error boundaries on route level
- Consistent component file structure