# React Component Reviewer

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

## Quick Reference

# 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

```
/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:

```
[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:

```
## 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

