Skip to content
Back to skills

Typescript React Reviewer

ASecurity

Expert code reviewer for TypeScript + React 19 applications. Use when reviewing React code, identifying anti-patterns, evaluating state management, or assessing code maintainability. Triggers: code review requests, PR reviews, React architecture evaluation, identifying code smells, TypeScript type safety checks, useEffect abuse detection, state management review.

  • 6 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added September 29, 2026
developmenttypescriptbashreactgitapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add AruNi-01/atmos --skill typescript-react-reviewer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typescript React Reviewer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Typescript React Reviewer
[![Security: A β€” Skills Directory](https://www.skillsdirectory.com/api/skills/aruni-01-typescript-react-reviewer/badge)](https://www.skillsdirectory.com/skills/aruni-01-typescript-react-reviewer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: typescript-react-reviewer
version: "1.2.0"
description: "Expert code reviewer for TypeScript + React 19 applications. Use when reviewing React code, identifying anti-patterns, evaluating state management, or assessing code maintainability. Triggers: code review requests, PR reviews, React architecture evaluation, identifying code smells, TypeScript type safety checks, useEffect abuse detection, state management review."
---

# TypeScript + React 19 Code Review Expert

Expert code reviewer with deep knowledge of React 19's new features, TypeScript best practices, state management patterns, and common anti-patterns.

## Atmos Review Session Integration

When the prompt contains a `<review-agent-run>` block, the session may target either a **workspace** (isolated git worktree) or a **project** (the project's main checkout). The reviewer flow is target-agnostic β€” it only needs the `session`, `current_revision_guid`, and `run` GUIDs from the block β€” but respect the target kind if you need to read repo state (target kind is visible in the output of `atmos review session-show --session <session_guid>`).

Use the run/session metadata to create one inline comment per concrete finding:

```bash
atmos review create-comment \
  --session <session_guid> \
  --revision <current_revision_guid> \
  --file <path> \
  --side new \
  --start-line <line> \
  --end-line <line> \
  --title "<short title>" \
  --run <run_guid> \
  --body-stdin <<'EOF'
Severity: P1
Issue: ...
Suggestion: ...
EOF
```

Prefer `--body-stdin` (or `--body-file <path>`) for multi-line bodies; `--body "..."` is only for short single-line text. After the review is complete, call:

```bash
atmos review set-status --run <run_guid> succeeded --summary-stdin <<'EOF'
<one-paragraph summary>
EOF
```

If the run cannot be completed, call `atmos review set-status --run <run_guid> failed --message "<reason>"`.

For the full command surface (session discovery, comment reading, run lifecycle, body-input conventions, and workspace vs project semantics), see [`references/atmos-review-cli.md`](references/atmos-review-cli.md).

## Review Priority Levels

### 🚫 Critical (Block Merge)

These issues cause bugs, memory leaks, or architectural problems:

| Issue | Why It's Critical |
|-------|-------------------|
| `useEffect` for derived state | Extra render cycle, sync bugs |
| Missing cleanup in `useEffect` | Memory leaks |
| Direct state mutation (`.push()`, `.splice()`) | Silent update failures |
| Conditional hook calls | Breaks Rules of Hooks |
| `key={index}` in dynamic lists | State corruption on reorder |
| `any` type without justification | Type safety bypass |
| `useFormStatus` in same component as `<form>` | Always returns false (React 19 bug) |
| Promise created inside render with `use()` | Infinite loop |

### ⚠️ High Priority

| Issue | Impact |
|-------|--------|
| Incomplete dependency arrays | Stale closures, missing updates |
| Props typed as `any` | Runtime errors |
| Unjustified `useMemo`/`useCallback` | Unnecessary complexity |
| Missing Error Boundaries | Poor error UX |
| Controlled input initialized with `undefined` | React warning |

### πŸ“ Architecture/Style

| Issue | Recommendation |
|-------|----------------|
| Component > 300 lines | Split into smaller components |
| Prop drilling > 2-3 levels | Use composition or context |
| State far from usage | Colocate state |
| Custom hooks without `use` prefix | Follow naming convention |

## Quick Detection Patterns

### useEffect Abuse (Most Common Anti-Pattern)

```typescript
// ❌ WRONG: Derived state in useEffect
const [firstName, setFirstName] = useState('');
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);

// βœ… CORRECT: Compute during render
const fullName = firstName + ' ' + lastName;
```

```typescript
// ❌ WRONG: Event logic in useEffect
useEffect(() => {
  if (product.isInCart) showNotification('Added!');
}, [product]);

// βœ… CORRECT: Logic in event handler
function handleAddToCart() {
  addToCart(product);
  showNotification('Added!');
}
```

### React 19 Hook Mistakes

```typescript
// ❌ WRONG: useFormStatus in form component (always returns false)
function Form() {
  const { pending } = useFormStatus();
  return <form action={submit}><button disabled={pending}>Send</button></form>;
}

// βœ… CORRECT: useFormStatus in child component
function SubmitButton() {
  const { pending } = useFormStatus();
  return <button type="submit" disabled={pending}>Send</button>;
}
function Form() {
  return <form action={submit}><SubmitButton /></form>;
}
```

```typescript
// ❌ WRONG: Promise created in render (infinite loop)
function Component() {
  const data = use(fetch('/api/data')); // New promise every render!
}

// βœ… CORRECT: Promise from props or state
function Component({ dataPromise }: { dataPromise: Promise<Data> }) {
  const data = use(dataPromise);
}
```

### State Mutation Detection

```typescript
// ❌ WRONG: Mutations (no re-render)
items.push(newItem);
setItems(items);

arr[i] = newValue;
setArr(arr);

// βœ… CORRECT: Immutable updates
setItems([...items, newItem]);
setArr(arr.map((x, idx) => idx === i ? newValue : x));
```

### TypeScript Red Flags

```typescript
// ❌ Red flags to catch
const data: any = response;           // Unsafe any
const items = arr[10];                // Missing undefined check
const App: React.FC<Props> = () => {}; // Discouraged pattern

// βœ… Preferred patterns
const data: ResponseType = response;
const items = arr[10]; // with noUncheckedIndexedAccess
const App = ({ prop }: Props) => {};  // Explicit props
```

## Review Workflow

1. **Scan for critical issues first** - Check for the patterns in "Critical (Block Merge)" section
2. **Check React 19 usage** - See [react19-patterns.md](references/react19-patterns.md) for new API patterns
3. **Evaluate state management** - Is state colocated? Server state vs client state separation?
4. **Assess TypeScript safety** - Generic components, discriminated unions, strict config
5. **Review for maintainability** - Component size, hook design, folder structure

## Generate the Report

Write the review report to the specified file path. The report MUST follow this exact structure:

> **Traceability frontmatter**: When this review is run inside an Atmos review session, the prompt will include a ready-to-copy YAML frontmatter block (under the key `atmos_review`). Write that block **verbatim** as the very first lines of the report file, before the `# TypeScript + React 19 Code Review Report` heading. Do not edit, reformat, or omit any field. When there is no session context, omit the frontmatter.

Example of the frontmatter the prompt will supply:

```yaml
---
atmos_review:
  session_guid: "<guid>"
  run_guid: "<guid>"
  base_revision_guid: "<guid>"
  current_revision_guid: "<guid>"
  skill_id: "typescript-react-reviewer"
  generated_at: "<ISO-8601 UTC>"
---
```

```markdown
# TypeScript + React 19 Code Review Report

| Entry | Details |
| :--- | :--- |
| **Date** | YYYY-MM-DD HH:MM |
| **Reviewer** | AI (typescript-react-reviewer) |
| **Scope** | [description of what was reviewed β€” git diff / specific files / commit range] |
| **Project Stack** | TypeScript + React 19 (detected frameworks/libraries) |
| **Overall Assessment** | **APPROVE** \| **REQUEST_CHANGES** \| **COMMENT** |

---

## Summary

| Metric | Value |
|--------|-------|
| Files Reviewed | X |
| Lines Changed | +Y / -Z |
| Critical Issues | N |
| High Priority | N |
| Architecture Issues | N |

---

## Findings by Priority

### 🚫 Critical
> None found. βœ…
(or list each finding with file, line, impact, and fix)

### ⚠️ High Priority
(same format)

### πŸ“ Architecture/Style
(same format)

---

## Recommended Next Steps

1. Address any critical bugs (P0)
2. Refactor high-priority anti-patterns
3. Consider architectural improvements
```

## Reference Documents

For detailed patterns and examples:

- **[react19-patterns.md](references/react19-patterns.md)** - React 19 new hooks (useActionState, useOptimistic, use), Server/Client Component boundaries
- **[antipatterns.md](references/antipatterns.md)** - Comprehensive anti-pattern catalog with fixes
- **[checklist.md](references/checklist.md)** - Full code review checklist for thorough reviews
- **[atmos-review-cli.md](references/atmos-review-cli.md)** - Shared Atmos review CLI reference (symlinked from `atmos-review-fix`)

## State Management Quick Guide

| Data Type | Solution |
|-----------|----------|
| Server/async data | TanStack Query (never copy to local state) |
| Simple global UI state | Zustand (~1KB, no Provider) |
| Fine-grained derived state | Jotai (~2.4KB) |
| Component-local state | useState/useReducer |
| Form state | React 19 useActionState |

### TanStack Query Anti-Pattern

```typescript
// ❌ NEVER copy server data to local state
const { data } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos });
const [todos, setTodos] = useState([]);
useEffect(() => setTodos(data), [data]);

// βœ… Query IS the source of truth
const { data: todos } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos });
```

## TypeScript Config Recommendations

```json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "exactOptionalPropertyTypes": true
  }
}
```

`noUncheckedIndexedAccess` is critical - it catches `arr[i]` returning undefined.

## Immediate Red Flags

When reviewing, flag these immediately:

| Pattern | Problem | Fix |
|---------|---------|-----|
| `eslint-disable react-hooks/exhaustive-deps` | Hides stale closure bugs | Refactor logic |
| Component defined inside component | Remounts every render | Move outside |
| `useState(undefined)` for inputs | Uncontrolled warning | Use empty string |
| `React.FC` with generics | Generic inference breaks | Use explicit props |
| Barrel files (`index.ts`) in app code | Bundle bloat, circular deps | Direct imports |

Files in this skill

  • SKILL.md9.8 KB
  • references/antipatterns.md12 KB
  • references/checklist.md7.4 KB
  • references/react19-patterns.md7.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.