
Typescript React Reviewer
Run structured TypeScript and React 19 code review on PRs and local changes, with merge-blocking rules for hooks, effects, and types.
Overview
TypeScript + React Reviewer is an agent skill most often used in Ship review (also Build frontend) that audits React 19 and TypeScript code for anti-patterns and merge-blocking defects.
Install
npx skills add https://github.com/dotneet/claude-code-marketplace --skill typescript-react-reviewerWhat is this skill?
- Merge-blocking checks for useEffect derived state, missing cleanup, and Rules of Hooks violations
- React 19 specifics including useFormStatus placement and use() promise-in-render loops
- Flags key={index}, any abuse, incomplete dependency arrays, and direct state mutation
- Structured Critical versus High priority review levels for PR commentary
- Covers state management smells and TypeScript type safety on props
- 8 Critical merge-blocking issue categories documented
- 2-tier review priority model: Critical and High
Adoption & trust: 7.3k installs on skills.sh; 1 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are merging React 19 UI fast and need a consistent reviewer who catches hooks abuse and type holes that tests miss.
Who is it for?
Solo builders and tiny teams using TypeScript + React 19 who want PR-grade review without waiting on a human reviewer.
Skip if: Non-React stacks, design-only critiques, or repos where you only want formatting fixes without architectural judgment.
When should I use this skill?
Code review requests, PR reviews, React architecture evaluation, code smells, TypeScript type safety checks, useEffect abuse detection, or state management review.
What do I get? / Deliverables
You get prioritized review comments labeled Critical or High so you fix merge-blockers and stale-closure bugs before the PR lands.
- Prioritized review report with Critical and High sections
- Actionable fixes tied to documented anti-patterns
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Canonical shelf is Ship review because triggers explicitly name PR reviews and architecture evaluation before merge. Review subphase fits the priority tables—Critical block merge versus High priority—and React 19-specific footguns.
Where it fits
You finish a new client feature and want hooks and derived-state issues caught before you open a PR.
You paste a PR diff and need Critical versus High findings aligned with React 19 merge policy.
Flaky UI tests trace back to key={index}; the skill flags list identity bugs worth fixing before QA sign-off.
How it compares
A React-19-aware review playbook—not a generic linter config or backend API security audit.
Common Questions / FAQ
Who is typescript-react-reviewer for?
Indie web developers shipping TypeScript React 19 apps who want agent-driven PR and architecture review with explicit severity tiers.
When should I use typescript-react-reviewer?
During Ship review on PRs; during Build frontend when refactoring hooks or state; whenever you need anti-pattern detection, useEffect abuse checks, or TypeScript safety on props.
Is typescript-react-reviewer safe to install?
It analyzes code you provide and does not require bundled credentials; review the Security Audits panel on this Prism page before installing marketplace skills.
SKILL.md
READMESKILL.md - Typescript React Reviewer
# 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. ## 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