react-stinky

Installation
SKILL.md

React Stinky

A holistic code-smell detector for React and TypeScript. It finds the patterns that make a component, a hook, or a module hard to read, reason about, and change, explains the cost of each, and proposes a concrete fix. Coverage spans prop and API design, state and data flow, effects and lifecycle, component structure, rendering correctness, accessibility, async and error handling, and TypeScript discipline. The full catalog with detection signals, fixes, exceptions, and sources is in catalog.md; read it before running a scan.

It defers two neighboring concerns to sibling skills so it does not duplicate them: memoization (useMemo, useCallback, React.memo) to react-compiler, and color literals to theme-colors. If those are not installed, note the finding in one line and move on. Everything else about day-to-day React maintainability is in scope.

What it sniffs for

Nine pillars. The categories under each, with detection signals and sources, are in catalog.md. The background models the findings lean on (controlled vs uncontrolled, render snapshots, effects as synchronization, one fact one home, impossible states, the composition layer, hydration) are separate linked concepts under references/concepts/; read one when a finding needs the underlying model explained, not just named.

  1. Component API and props (the backbone, 18 categories). Component and prop naming, boolean and callback conventions, string-union variants over boolean flags, discriminated unions, controlled and uncontrolled state, children and slot composition, render props, generics, extending HTML, refs, styling APIs, accessibility props, server-component boundaries, JSDoc.
  2. State and data flow. Derivable values held in useState, props copied into state, two sources of truth for one fact, prop drilling, stale closures in timers and async continuations, useState/useRef role confusion, god contexts and unstable provider values.
  3. Effects and lifecycle. Effects that compute derived data, replace an event handler, or push data up to the parent; fetches and subscriptions and timers with no cleanup (races and leaks); dependency arrays that do not match what the effect reads; state reset by an effect instead of key.
  4. Component structure and hooks. God components (and god hooks) doing fetching, logic, and presentation at once; views coupled to their environment, with data access and domain rules that belong a layer up and should arrive as behavior-named props (the test is whether it renders in Storybook without mocks); a component defined inside another (remounts every render); stateful logic that wants a custom hook; conditional hooks; positional-parameter sprawl on a hook or util.
  5. Rendering correctness. Array index as key on a list that reorders or edits, direct mutation of state or props, impure renders (randomness and clock reads, setState during render, hydration-unsafe browser reads), the stray 0 leaked by &&, nested ternaries, copy-pasted JSX blocks.
  6. Accessibility in markup. onClick on a non-interactive element with no role, tabIndex, or keyboard handler; div soup where semantic elements belong; form controls with no associated label; broken focus management in hand-rolled modals and menus.
  7. Async, events, and error handling. Async handlers that swallow failures or allow double submits, missing error boundaries around risky subtrees, unsanitized HTML and URL sinks (dangerouslySetInnerHTML, javascript: hrefs).
  8. TypeScript discipline. any and as any and @ts-ignore, lying as casts and non-null !, loose internal types (object, Function, stringly-typed enums), untyped catch blocks, unions switched on without an exhaustiveness check.
  9. Cross-file duplication (folder and repo scope only). A component re-implemented inline where a reusable one exists, the same hook or utility copied across files, a type declared in two places. Method in duplication-pass.md.
Installs
117
Repository
saschb2b/skills
GitHub Stars
12
First Seen
Jun 16, 2026
react-stinky — saschb2b/skills