New
Introducing React Doctor for Enterprise

react-doctor/no-derived-useState

Remove useState and compute the value inline: `const value = transform(propName)`

  • Category: State & Effects
  • Severity: warn
  • Source: oxlint-plugin-react-doctor
  • Framework: global
  • Enabled when: always

Validation prompt

Use this to decide whether a fired diagnostic is real or a false positive.

Fires on useState(propName) or useState(propName.nested) where propName is a destructured prop or props.x reference tracked by the per-component prop-stack. Only direct Identifier and non-computed MemberExpression initializers are checked — useState(transform(prop)) or useState(() => transform(prop)) will not trigger. False positive: an intentionally uncontrolled-component pattern that captures the initial prop value ONCE and never re-syncs.

Fix prompt

Use this once validation confirms the diagnostic is real.

Delete the useState and read the prop directly during render: const value = transform(propName). If you need a separate editable local copy that resets when the prop changes, lift the prop to a key on the component — <Form key={userId} initialValue={...} /> — so React remounts with a fresh useState on each change. See https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes

More State & Effects rules from the rules reference:

  • 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