React Best-Practices Review
After editing several TSX/JSX files, run through this condensed checklist to catch common issues before they compound.
Component Structure
- One component per file — colocate helpers only if they are private to that component
- Named exports over default exports for better refactoring and tree-shaking
- Props interface defined inline or colocated, not in a separate
types.tsunless shared - Destructure props in the function signature:
function Card({ title, children }: CardProps) - Avoid barrel files (
index.tsre-exports) in large projects — they hurt tree-shaking
Hooks
- Rules of Hooks — never call hooks conditionally or inside loops
- Custom hooks — extract reusable logic into
use*functions when two or more components share it - Dependency arrays — list every reactive value; lint with
react-hooks/exhaustive-deps useCallback/useMemo— use only when passing to memoized children or expensive computations, not by defaultuseEffectcleanup — return a cleanup function for subscriptions, timers, and abort controllers
State Management
- Colocate state — keep state as close as possible to where it is consumed
- Derive, don't sync — compute values from existing state instead of adding
useEffectto mirror state - Avoid prop drilling past 2–3 levels — use context or composition (render props / children)
- Server state — use React Query, SWR, or Server Components instead of manual fetch-in-effect
Accessibility (a11y)
- Semantic HTML first — use
<button>,<a>,<nav>,<main>, etc. before reaching for<div onClick> alton every<img>— decorative images getalt=""- Keyboard navigation — interactive elements must be focusable and operable via keyboard
aria-*attributes — only when native semantics are insufficient; don't redundantly label
Performance
React.memo— wrap pure display components that re-render due to parent changes- Lazy loading — use
React.lazy+Suspensefor route-level code splitting - List keys — use stable, unique IDs; never use array index as key for reorderable lists
- Avoid inline object/array literals in JSX props — they create new references every render
- Image optimization — use
next/imageor responsivesrcSet; avoid unoptimized<img>in Next.js
TypeScript Patterns
React.FCis optional — prefer plain function declarations with explicit return typesPropsWithChildren— use when the component acceptschildrenbut has no other custom props- Event handlers — type as
React.MouseEvent<HTMLButtonElement>, notany - Generics for reusable components — e.g.,
function List<T>({ items, renderItem }: ListProps<T>) as constfor config objects — ensures literal types for discriminated unions and enums
Design System Consistency
- Prefer shadcn primitives in Vercel-stack apps: Button, Input, Tabs, Dialog, AlertDialog, Sheet, Table, Card before building ad-hoc equivalents.
- Reject container soup: repeated
div rounded-xl border p-6blocks usually mean stronger composition primitives are missing. - Typography consistency: use Geist Sans and Geist Mono consistently; reserve monospace for code, metrics, IDs, and timestamps.
Review Workflow
- Scan recent TSX edits for the patterns above
- Flag any violations with file path and line reference
- Suggest minimal fixes — do not refactor beyond what is needed
- If multiple issues exist in one file, batch them into a single edit