react-effects-audit
npx machina-cli add skill fusengine/agents/react-effects-audit --openclawTarget: $ARGUMENTS
React Effects Audit
Overview
Scan React codebases to detect unnecessary useEffect usage based on official React documentation ("You Might Not Need an Effect"). Reports anti-patterns with severity, location, and recommended fixes.
Agent Workflow (MANDATORY)
PHASE 1: Scan target files (Glob *.tsx, *.jsx, *.ts, *.js)
PHASE 2: Detect anti-patterns (Grep detection rules)
PHASE 3: Analyze context (Read flagged files)
PHASE 4: Generate report with fixes
Anti-Pattern Summary
| # | Anti-Pattern | Severity | Detection |
|---|---|---|---|
| 1 | Derived state in Effect | WARNING | useEffect + setState from other state/props |
| 2 | Expensive calculation in Effect | WARNING | useEffect + setState with filter/map/reduce |
| 3 | State reset via Effect | WARNING | useEffect resets state when prop changes |
| 4 | Event logic in Effect | CRITICAL | User interaction logic inside useEffect |
| 5 | Parent notification via Effect | WARNING | useEffect calls parent onChange/onUpdate |
| 6 | Effect chains | CRITICAL | Multiple useEffect triggering each other |
| 7 | Missing cleanup in fetch | CRITICAL | useEffect fetch without cleanup/AbortController |
| 8 | Manual store subscription | WARNING | addEventListener/subscribe in useEffect |
| 9 | App init in Effect | INFO | One-time init logic in useEffect(fn, []) |
Severity Levels
| Level | Meaning | Action |
|---|---|---|
| CRITICAL | Bugs, race conditions, memory leaks | Fix immediately |
| WARNING | Performance issues, unnecessary re-renders | Fix same session |
| INFO | Readability, minor inefficiency | Fix if time allows |
Reference Guide
Skill References
| Reference | When to Consult |
|---|---|
| anti-patterns.md | Understanding each anti-pattern |
| detection-rules.md | Grep patterns for scanning |
| fix-patterns-core.md | Fix examples #1-5 |
| fix-patterns-advanced.md | Fix examples #6-9 |
| report-format.md | Generating audit report |
SOLID Cross-References (MANDATORY)
This audit complements existing SOLID skills. Always cross-reference:
| Project Type | SOLID Skill | Key Rule |
|---|---|---|
| Next.js | fuse-nextjs:solid-nextjs | No useEffect for data fetching; use Server Components |
| React | fuse-react:solid-react | No useEffect for data fetching; use TanStack Query |
Integration: When auditing a Next.js or React project, also load the corresponding SOLID skill to check architecture-level violations (file size, interface separation, business logic in components).
Quick Start
1. Glob **/*.{tsx,jsx} in target directory
2. Detect project type (next.config.* → Next.js, package.json → React)
3. Load corresponding SOLID skill references if applicable
4. For each detection rule in detection-rules.md:
→ Grep pattern across all files
→ Read flagged files for context analysis
→ Confirm or dismiss (false positive check)
5. For each confirmed finding:
→ Identify severity from anti-patterns.md
→ Propose fix from fix-patterns-core.md or fix-patterns-advanced.md
→ Cross-check with SOLID rules (SRP, file size, hooks separation)
6. Output report using report-format.md
React 19+ Considerations
| Feature | Impact on Audit |
|---|---|
| React Compiler | Auto-memoizes; useMemo less needed but Effect anti-patterns still apply |
| useEffectEvent | Stable in 19.2; solves stale closure in Effects without adding deps |
| Activity API | Alternative to conditional rendering; reduces mount/unmount Effects |
| useSyncExternalStore | Replaces manual subscription Effects (anti-pattern #8) |
| Server Components | Eliminates many data-fetching Effects entirely |
Forbidden Behaviors
- Do NOT auto-fix without showing the finding first
- Do NOT flag Effects that synchronize with external systems (valid use)
- Do NOT flag data fetching Effects that have proper cleanup
- Do NOT ignore context: always Read the file before confirming a finding
Source
git clone https://github.com/fusengine/agents/blob/main/plugins/ai-pilot/skills/react-effects-audit/SKILL.mdView on GitHub Overview
This skill scans React codebases to detect unnecessary useEffect usage based on the 'You Might Not Need an Effect' guidance. It reports anti-patterns with severity, location, and recommended fixes to reduce bugs and improve performance.
How This Skill Works
The agent scans target files (tsx/jsx/ts/js), applies grep-based anti-pattern detections for nine patterns, analyzes context around flagged code, and then generates a prioritized report with suggested fixes categorized by severity.
When to Use It
- During code reviews to catch unnecessary or harmful useEffect patterns
- When refactoring components with complex effects to simplify logic
- During performance audits to identify wasted renders from effects
- When onboarding a React project to enforce best practices around effects
- In CI or pre-merge checks to prevent anti-patterns from being merged
Quick Start
- Step 1: Glob **/*.{tsx,jsx} in the target directory
- Step 2: Detect project type (Next.js vs React) and load corresponding SOLID references
- Step 3: For each detection rule, grep, review context, confirm findings, and generate a report with fixes
Best Practices
- Glob the correct file extensions (tsx, jsx, ts, js) to ensure full coverage
- Read flagged files in context before dismissing false positives
- Map each anti-pattern to a concrete fix from fix-patterns-core/advanced
- Cross-check findings with SOLID references for architecture concerns
- Validate fixes with tests and regression checks to avoid breaking behavior
Example Use Cases
- Derived state in Effect: useEffect calls setState derived from props; fix by deriving state outside effect or using useMemo
- Expensive calculation in Effect: expensive filter/map/reduce inside an effect; fix by computing outside or memoizing
- Missing cleanup in fetch: useEffect performs fetch without cleanup; fix with AbortController or cancellation
- Event logic in Effect: user interaction handled inside useEffect; fix by moving to explicit event handlers
- App init in Effect: one-time initialization inside useEffect(fn, []) during app startup; fix by running init in module scope or useEffect with proper deps