con un clic
react-hook-review
// Review React hooks against design philosophy. Checks return values, SSR safety, state design, effect usage, TypeScript patterns, and performance.
// Review React hooks against design philosophy. Checks return values, SSR safety, state design, effect usage, TypeScript patterns, and performance.
Design React APIs and abstractions in a React-like way. Covers declarative interfaces, lifecycle-safe abstractions, minimal surfaces, zero-dependency bias, type safety, and documentation.
Write React hooks following design philosophy. Covers naming, return values, SSR safety, state design, effect patterns, TypeScript, and performance.
Create branches following repo conventions. Use when creating branches, starting new features.
PR/code review. 100% coverage, SSR safety, JSDoc validation. Use when reviewing code, checking PRs.
Create commits following repo conventions. Use when committing changes, creating commit messages.
Complete workflow from new Hook/Component/Util development to deployment. Use when starting new feature development.
| name | react-hook-review |
| description | Review React hooks against design philosophy. Checks return values, SSR safety, state design, effect usage, TypeScript patterns, and performance. |
Review hooks against coding principles and usage patterns. Report findings by severity.
Treat C1, C7, and C14 as opinionated conventions unless the target codebase explicitly adopts them. Report them as stronger findings when the repository standard is clear; otherwise phrase them as consistency recommendations.
Return values (C1) — Always return objects, even for single values. { value } not bare primitives.
Why: Named fields, order-independent, extensible without breaking changes.
SSR-safe init (C2) — useState(FIXED) + useEffect(sync). No browser API in initializer.
Why: Server has no window — crashes or hydration mismatch.
Note: For explicitly client-only hooks, a guarded lazy initializer can be acceptable.
Cleanup (C3) — Every useEffect with side effects returns cleanup (listeners, timers, AbortController). Why: Memory leaks. StrictMode double-mount exposes missing cleanup immediately.
No any (C4) — Use generics <T>. Justified eslint-disable with comment is acceptable.
Why: any propagates and defeats the type system.
Named exports (C5) — No default exports. Tree-shaking + unambiguous imports.
Strict booleans (C6) — == null for nullish, !== undefined for distinction. No implicit if (value).
Why: 0, "", false are falsy — silent bugs.
Object parameters (C7) — Hook params as object props, not positional args. Why: Order-independent, self-documenting, extensible.
JSDoc 4-tag (C9) — @description + @param + @returns + @example on every public API. Why: AI doc generation quality + IDE tooltips.
Performance (C10) — Throttle (16ms) for >30 events/sec, deduplicate unchanged, startTransition for non-urgent. Only applies to high-frequency event hooks.
Zero deps (C12) — No runtime dependencies. peerDependencies only.
Dependency isolation (C13) — Inject external dependencies as parameters rather than importing them directly inside hooks. Why: Testability + replaceability.
Guard clauses (C8) — Early return over nested if-else. Flat success path. Trade-off: Stylistic preference with no functional impact.
Function keyword (C11) — function for declarations, arrows for inline callbacks only.
Trade-off: Consistent style, but arrow declarations are valid JS.
Named useEffect (C14) — useEffect(function handleX() {...}) not arrows.
Why: "handleResize" vs "anonymous" in error stacks. Trade-off: more verbose.
useEffect for derived values.initialX.key={id} to remount, not useEffect to clear state.ignore flag or AbortController for every async effect.useMount. Purpose-specific hooks only.codecode