# React Typescript Review

> Review React + TypeScript code — components, hooks, a PR, or a pasted file — the way a senior frontend engineer would, prioritizing correctness, hooks bugs, performance, accessibility, and type safety over style nits. Use whenever the user asks you to review, critique, or check React/TSX/JSX code or a frontend PR, or asks "is this component right?" — even if they don't say "code review".

- Skill: `jacobjustin8/react-typescript-review` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add jacobjustin8/react-typescript-review`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jacobjustin8/react-typescript-review/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: jacobjustin8 (https://skillmd.com/u/jacobjustin8)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jacobjustin8/react-typescript-review

---


# React + TypeScript review

Review the way a senior frontend engineer whose reviews people trust would: catch
the bugs that actually ship broken UI, and skip the bikeshedding. The goal is a
change that leaves the frontend healthier, with the author's time respected.
Prettier/ESLint already handle formatting — don't spend review on it.

## Review in priority order

Read every line you approve, but spend attention where the risk is highest.

1. **Hooks correctness — the #1 source of real React bugs.**
   - Hooks must be called unconditionally at the top level — never inside
     conditionals, loops, or nested functions. Flag any conditional hook.
   - `useEffect` / `useCallback` / `useMemo` dependency arrays must include every
     reactive value they read. A missing dependency is a stale-closure bug waiting
     to happen; an `eslint-disable` on the deps rule is only acceptable with a
     comment explaining why. Watch for effects that should have a cleanup function
     (subscriptions, timers, listeners) and don't.

2. **Type safety.** Flag `any` (it disables the very protection TS provides —
   prefer a real interface or `unknown` + narrowing). Question `as` assertions
   without justification; prefer runtime validation (e.g. Zod) for external data.
   Check optional values are actually guarded (`?.`, `??`, narrowing) rather than
   accessed blindly.

3. **Correctness & data flow.** Does it handle loading, empty, and error states,
   not just the happy path? Are async calls awaited and their rejections handled?
   Does state update logic avoid mutating state directly?

4. **Performance — but only where it's real.** Inline object/array/function props
   defeat `React.memo` and cause re-renders; flag them when the child is memoized
   or the list is large. Flag expensive work on every render that belongs in
   `useMemo`. **Reject index-as-key** (and missing keys) in dynamic lists — it
   causes subtle state/DOM bugs. Don't demand memoization everywhere, though —
   premature `useMemo`/`useCallback` adds noise and its own bugs.

5. **Accessibility.** Real elements over `div onClick` (`<button>`, `<a>`);
   icon-only buttons need an `aria-label`; form inputs need associated labels;
   interactive things must be keyboard-reachable. These are correctness issues for
   a share of your users, not polish.

6. **Security.** Block `dangerouslySetInnerHTML` on unsanitized input (XSS). No
   secrets/API keys in client code. No logging of tokens or PII.

7. **Structure.** Overgrown components (~200+ lines doing many things) want
   splitting; deep prop-drilling suggests context or a custom hook; business logic
   and data-fetching belong out of JSX in pure functions / hooks.

## What NOT to flag

Formatting (Prettier's job), personal style (map vs. loop, naming aesthetics), and
full rewrites. Suggest approaches; don't rewrite the author's block for them.
Blocking on preference is what makes a reviewer dreaded rather than valued.

## Tone

Ask questions where you might lack context ("is there a reason the empty state
isn't handled?"), explain the *why* so the author learns the rule, offer the fix,
and note something that's genuinely good. Distinguish blocking issues (a hooks
bug, a type hole, an XSS) from optional suggestions — prefix the latter with
"Nit:".

## Output

```
## Verdict
<Approve / Approve with nits / Needs changes>  — one line on the headline.

## Blocking
<Numbered: where, what's wrong, why it matters, suggested fix. Omit if none.>

## Non-blocking
<Suggestions and questions; prefix optional polish with "Nit:".>

## What's good
<Briefly reinforce what was done well.>
```

If you were given a snippet without its surroundings, review what's visible and
say what you'd need (the parent, the types, the tests) to be sure — don't invent
context.

