react-doctor/no-jsx-element-type
Widen the return type from JSX.Element to React.ReactNode: function App(): React.ReactNode
- Category: Bugs
- Severity: warn
- Source:
oxlint-plugin-react-doctor - Framework: global
- Enabled when: always
- Default: Enabled
Validation prompt
Use this to decide whether a fired diagnostic is real or a false positive.
Fires when a function's return-type annotation is exactly the qualified name JSX.Element — a TSTypeReference whose typeName is a TSQualifiedName with left Identifier named JSX and right Identifier named Element — checked on the returnType of FunctionDeclaration, ArrowFunctionExpression, FunctionExpression, ambient declare function (TSDeclareFunction), and TSMethodSignature. It deliberately still fires even when a local namespace JSX shadows the global one. False positive to suppress: any return type that is NOT the bare JSX.Element qualified name — React.JSX.Element (its TSQualifiedName left is itself a qualified name, not the Identifier JSX), React.ReactElement, or React.ReactNode (all valid), no annotation at all, or a non-JSX type like string/void. Also suppress when JSX.Element appears somewhere other than a function return type, e.g. a variable annotation const element: JSX.Element = <div /> — that position is not reported.
Fix prompt
Use this once validation confirms the diagnostic is real.
Replace the JSX.Element return annotation with React.ReactNode, e.g. function App(): React.ReactNode { ... } or const App = (): React.ReactNode => <div />. JSX.Element is too narrow because it excludes the null, string, number, and fragment values components legitimately return; React.ReactNode covers all of them. If the component truly always returns a single element and you need that guarantee, React.ReactElement is the narrower correct choice — but never JSX.Element. Ensure React (or ReactNode) is imported.
Related rules
More Bugs rules from the rules reference:
react-doctor/no-legacy-class-lifecycles: Move side effects in `componentWillMount` to `componentDidMount`; replace `componentWillReceiveProps` with `componentDidUpdate` (compare prevProps) or the static `getDerivedStateFromProps` for pure state derivation; replace `componentWillUpdate` with `getSnapshotBeforeUpdate` paired with `componentDidUpdate`. The `UNSAFE_` prefix only silences the warning — React 19 removes both forms.react-doctor/no-legacy-context-api: Replace `childContextTypes` + `getChildContext` with `const MyContext = createContext(...)` + `<MyContext.Provider value={...}>`; replace `contextTypes` with `static contextType = MyContext` (single context) or `useContext()` / `use()` from a function component. The provider and every consumer must migrate together — partial migrations leave consumers reading the wrong context.react-doctor/no-locale-format-in-render: Locale/timezone formatting during renderreact-doctor/no-match-media-in-state-initializer: matchMedia in state initializerreact-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