active

React Component Reviewer

Safe

Deep review of React/TSX components against a 12-point checklist: hook violations, missing keys, ARIA attributes, memoization, prop drilling, missing dependencies, and more.

@atapifire/react-component-reviewer

react
typescript
code-review
accessibility
hooks

React Component Reviewer

Purpose: Perform a deep, systematic review of a React TypeScript component (.tsx) against a specific 12-point checklist. Goes beyond generic code review to catch React-specific anti-patterns that general reviewers miss. Produces annotated findings with exact fix suggestions.


Invocation

code
/react-review <file.tsx>

The 12-Point Checklist

1. Hook Order Violations

  • Are hooks called conditionally or inside loops? (breaks Rules of Hooks)
  • Are hooks called in the same order on every render?

2. Missing key Props in Lists

  • Every .map() that returns JSX must have a stable key prop
  • key must not be the array index when the list can reorder or filter

3. Missing or Incorrect ARIA Attributes

  • Interactive elements (<div onClick>, <span onClick>) must have role and keyboard handlers
  • Images must have alt attribute (empty string alt="" for decorative images)
  • Form inputs must have associated <label> via htmlFor or aria-label
  • Modal/dialog elements must have aria-modal, role="dialog", and focus trap

4. Missing React.memo on Pure Components

  • Components that receive complex objects as props and re-render frequently
  • Components that are used inside lists and receive non-primitive props
  • Note: memo is not needed everywhere — flag only genuine candidates

5. Prop Drilling Deeper Than 2 Levels

  • Props passed through 3+ component layers without being used in intermediate components
  • Suggest: React Context, component composition, or lifting state differently

6. useEffect Missing Dependencies or Stale Closures

  • Variables used inside useEffect but not in the dependency array
  • Functions defined outside useEffect used inside without being in deps
  • Missing useCallback on functions passed as deps

7. Unhandled Loading and Error States

  • Data-fetching components must render loading state (skeleton, spinner, or message)
  • Data-fetching components must render error state with actionable message
  • Empty state when data is [] or null should be handled

8. Hardcoded Strings That Should Be Constants

  • URLs, error messages, magic numbers used directly in JSX
  • Strings used in multiple places without being defined as constants

9. any Type Usage

  • Every any annotation in the component is a type safety hole
  • Suggest unknown with type narrowing, or proper interface definition

10. Missing Null Checks on Optional Props

  • Optional chaining (?.) used but result not checked before rendering
  • Props that could be undefined rendered without a fallback

11. Direct DOM Mutation

  • document.getElementById() or document.querySelector() inside a component
  • Suggest useRef() for DOM access

12. Missing Suspense Boundary for Async Components

  • Components using use(), React.lazy(), or async Server Components
  • Must be wrapped in <Suspense fallback={...}> at the appropriate level

Output Format

For each finding:

code
[SEVERITY] Checklist Item #N — file.tsx:line
Issue: [what's wrong]
Fix: [exact code change or pattern to use]

Severity:

  • CRITICAL — Will cause runtime errors or accessibility failures
  • HIGH — Causes incorrect behavior or major UX issues
  • MEDIUM — Performance or maintainability concern
  • LOW — Style or minor improvement

End with:

code
## Component Review Summary
Checklist items reviewed: 12/12
Issues found: [N] (Critical: N, High: N, Medium: N, Low: N)
Verdict: APPROVE / REQUEST CHANGES / NEEDS MAJOR REWORK

Rules

  • All 12 checklist items must be evaluated — "No issues" is a valid finding for each
  • Don't flag React.memo absence unless there's genuine evidence of unnecessary re-renders
  • key={index} in a static, non-reorderable list is acceptable — flag only if the list can change
  • ARIA issues are always HIGH or CRITICAL — accessibility is not optional

Playground

<!DOCTYPE html><html><head><meta charset='utf-8'><style>*{box-sizing:border-box;margin:0;padding:0}body{background:#0d1117;color:#e6edf3;font-family:monospace;font-size:12px;height:100vh;display:flex;flex-direction:column;overflow:hidden}.header{background:#161b22;border-bottom:1px solid #30363d;padding:8px 14px;font-size:11px;color:#8b949e;display:flex;justify-content:space-between;align-items:center;flex-shrink:0}.title{color:#58a6ff;font-weight:bold;font-size:13px}.panels{display:flex;flex:1;overflow:hidden}.panel{flex:1;overflow:auto;padding:12px;border-right:1px solid #30363d}.panel:last-child{border-right:none}.label{font-size:10px;color:#8b949e;text-transform:uppercase;letter-spacing:.08em;margin-bottom:6px}pre{white-space:pre-wrap;word-break:break-word;line-height:1.5}</style></head><body><div class='header'><span class='title'>React Component Reviewer</span><span>Example · SkillSlap</span></div><div class='panels'><div class='panel'><div class='label'>Input: React component</div><pre><span style='color:#8b949e'>function UserList() {</span>

<span style='color:#8b949e'> const [users, setUsers] = useState([])</span> <span style='color:#8b949e'> useEffect(() => {</span> <span style='color:#8b949e'> fetch('/api/users')</span> <span style='color:#8b949e'> .then(r => r.json())</span> <span style='color:#8b949e'> .then(setUsers)</span> <span style='color:#8b949e'> }, [users])</span> <span style='color:#8b949e'> return users.map(u =></span> <span style='color:#8b949e'> <div>{u.name}</div></span> <span style='color:#8b949e'> )</span> <span style='color:#8b949e'>}</span></pre></div><div class='panel'><div class='label'>Output: Review</div><pre><span style='color:#f85149'>🔴 Infinite loop (line 5)</span> <span style='color:#8b949e'>users in dep array triggers effect</span> <span style='color:#8b949e'>on every state update → infinite fetch.</span> <span style='color:#8b949e'>Fix: dep array should be []</span>

<span style='color:#f85149'>🔴 Missing key prop (line 8)</span> <span style='color:#8b949e'>React requires unique key on list items.</span> <span style='color:#8b949e'>Fix: <div key={u.id}></span>

<span style='color:#e3b341'>🟡 No loading/error state</span> <span style='color:#8b949e'>Blank screen while fetching, silent</span> <span style='color:#8b949e'>fail on error. Add isLoading + error.</span>

<span style='color:#e3b341'>🟡 No AbortController</span> <span style='color:#8b949e'>Fetch leaks if component unmounts.</span></pre></div></div></body></html>

Dormant$0/mo

$20 more to next tier

Info

Created February 20, 2026
Version 1.0.0
User-invoked
Terminal output

Embed

Add this skill card to any webpage.

<iframe src="https://skillslap.com/skill/f7dcf5ca-d694-4ea1-8ee1-0e3786e3a90f/embed"
        width="400" height="200"
        style="border:none;border-radius:12px;"
        title="SkillSlap Skill: React Component Reviewer">
</iframe>