Rules reference

305 engine rules grouped by category. Each rule pairs a validation prompt (when to confirm vs. suppress a finding) with a fix prompt (how to address it).

Every rule is also fetchable as Markdown at /docs/rules/{plugin}/{rule}.md — for example effect/no-derived-state.

Accessibility

Architecture

Bundle Size

Correctness

Next.js

Performance

React Compiler

  • react-hooks-js/component-hook-factories — Deprecated: this rule has been removed in 7.1.0.
  • react-hooks-js/error-boundaries — Validates usage of error boundaries instead of try/catch for errors in child components
  • react-hooks-js/globals — Validates against assignment/mutation of globals during render, part of ensuring that [side effects must render outside of render](https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
  • react-hooks-js/hooks — Validates the rules of hooks
  • react-hooks-js/immutability — Validates against mutating props, state, and other values that [are immutable](https://react.dev/reference/rules/components-and-hooks-must-be-pure#props-and-state-are-immutable)
  • react-hooks-js/incompatible-library — Validates against usage of libraries which are incompatible with memoization (manual or automatic)
  • react-hooks-js/preserve-manual-memoization — Validates that existing manual memoized is preserved by the compiler. React Compiler will only compile components and hooks if its inference [matches or exceeds the existing manual memoization](https://react.dev/learn/react-compiler/introduction#what-should-i-do-about-usememo-usecallback-and-reactmemo)
  • react-hooks-js/purity — Validates that [components/hooks are pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure) by checking that they do not call known-impure functions
  • react-hooks-js/refs — Validates correct usage of refs, not reading/writing during render. See the "pitfalls" section in [`useRef()` usage](https://react.dev/reference/react/useRef#usage)
  • react-hooks-js/set-state-in-effect — Validates against calling setState synchronously in an effect. This can indicate non-local derived data, a derived event pattern, or improper external data synchronization.
  • react-hooks-js/set-state-in-render — Validates against setting state during render, which can trigger additional renders and potential infinite render loops
  • react-hooks-js/static-components — Validates that components are static, not recreated every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering
  • react-hooks-js/todo — Unimplemented features
  • react-hooks-js/unsupported-syntax — Validates against syntax that we do not plan to support in React Compiler
  • react-hooks-js/use-memo — Validates usage of the useMemo() hook against common mistakes. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.
  • react-hooks-js/void-use-memo — Validates that useMemos always return a value and that the result of the useMemo is used by the component/hook. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.

React Native

Security

Server

State & Effects

  • effect/no-adjust-state-on-prop-change — Disallow adjusting state in an effect when a prop changes.
  • effect/no-chain-state-updates — Disallow chaining state changes in an effect.
  • effect/no-derived-state — Disallow storing derived state in an effect.
  • effect/no-event-handler — Disallow using state and an effect as an event handler.
  • effect/no-initialize-state — Disallow initializing state in an effect.
  • effect/no-pass-data-to-parent — Disallow passing data to parents in an effect.
  • effect/no-pass-live-state-to-parent — Disallow passing live state to parents in an effect.
  • effect/no-reset-all-state-on-prop-change — Disallow resetting all state in an effect when a prop changes.
  • react-doctor/effect-needs-cleanup — Return a cleanup function that releases the subscription / timer: `return () => target.removeEventListener(name, handler)` for listeners, `return () => clearInterval(id)` / `clearTimeout(id)` for timers, or `return unsubscribe` if the subscribe call already returned one
  • react-doctor/no-cascading-set-state — Combine into useReducer: `const [state, dispatch] = useReducer(reducer, initialState)`
  • react-doctor/no-derived-state-effect — For derived state, compute inline: `const x = fn(dep)`. For state resets on prop change, use a key prop: `<Component key={prop} />`. See https://react.dev/learn/you-might-not-need-an-effect
  • react-doctor/no-derived-use — Don't pass a promise created during render into use(); create it in a Server Component (or a stable cache) so its reference stays stable across renders
  • react-doctor/no-derived-useState — Remove useState and compute the value inline: `const value = transform(propName)`
  • react-doctor/no-did-mount-set-state — Derive state in getDerivedStateFromProps or initial state instead of calling this.setState in componentDidMount, which forces an extra render.
  • react-doctor/no-did-update-set-state — Avoid calling this.setState in componentDidUpdate; derive the value with getDerivedStateFromProps to prevent re-render loops
  • react-doctor/no-direct-state-mutation — Replace the mutation with a setter call that produces a new reference: `setItems([...items, newItem])`, `setItems(items.filter(x => x !== target))`, `setItems(items.toSorted(...))`. React only re-renders on a new reference, so in-place updates are silently dropped
  • react-doctor/no-effect-chain — Compute as much as possible during render (e.g. `const isGameOver = round > 5`) and write all related state inside the event handler that originally fires the chain. Each effect link adds an extra render and makes the code rigid as requirements evolve
  • react-doctor/no-effect-event-handler — Move the conditional logic into onClick, onChange, or onSubmit handlers directly
  • react-doctor/no-effect-event-in-deps — Call the useEffectEvent callback inside the effect body without listing it; its identity is intentionally unstable
  • react-doctor/no-event-trigger-state — Delete the trigger state (`useState(null)` plus the `useEffect` that watches it) and call the side-effect (`post(...)` / `navigate(...)` / `track(...)`) directly inside the event handler that previously called the setter. State should not exist purely to schedule effect runs
  • react-doctor/no-fetch-in-effect — Use `useQuery()` from @tanstack/react-query, `useSWR()`, or fetch in a Server Component instead
  • react-doctor/no-mirror-prop-effect — Delete both the `useState` and the `useEffect` and read the prop directly during render. Mirroring a prop into local state forces a stale first render before the effect re-syncs
  • react-doctor/no-mutable-in-deps — Read mutable values (`location.pathname`, `ref.current`) inside the effect body instead of in the deps array, or subscribe with `useSyncExternalStore`. Mutations to these don't trigger re-renders, so listing them in deps doesn't make the effect react to changes
  • react-doctor/no-prop-callback-in-effect — Lift the shared state into a Provider so both sides read the same source — no useEffect-driven sync needed
  • react-doctor/no-set-state-in-render — Move the setter call into a `useEffect`, an event handler, or replace the state with a value computed during render. Calling a setter at render time triggers another render, which calls the setter again — an infinite loop
  • react-doctor/no-will-update-set-state — Don't call this.setState in componentWillUpdate — move the update to getDerivedStateFromProps or componentDidUpdate.
  • react-doctor/prefer-use — Replace useContext(Context) with the React 19 use(Context) API, which reads the same value but may be called conditionally
  • react-doctor/prefer-use-effect-event — Wrap the callback with `useEffectEvent(callback)` (React 19+) and call the resulting binding from inside the sub-handler. The Effect Event captures the latest props/state without being a reactive dep, so the effect doesn't re-subscribe on every parent render. See https://react.dev/reference/react/useEffectEvent
  • react-doctor/prefer-use-sync-external-store — Replace the `useState(getSnapshot())` + `useEffect(() => store.subscribe(() => setSnapshot(getSnapshot())))` pair with `useSyncExternalStore(store.subscribe, getSnapshot)`. The hook handles tearing during concurrent renders and SSR snapshots; the manual subscribe pattern doesn't
  • react-doctor/prefer-useReducer — Group related state: `const [state, dispatch] = useReducer(reducer, { field1, field2, ... })`
  • react-doctor/rerender-dependencies — Extract to a useMemo, useRef, or module-level constant so the reference is stable

TanStack Query

TanStack Start