New
Introducing React Doctor for Enterprise

react-doctor/jsx-no-useless-fragment

Drop the fragment when it wraps a single child or holds multiple children directly under an HTML tag.

Validation prompt

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

Fires on a fragment (<></>, <Fragment>, or <React.Fragment>) with fewer than two meaningful children — whitespace-only text containing a newline is treated as padding and ignored, so <><Foo /></> and <div><>foo</></div> both trip the single-child path. It also fires, separately, on a fragment with 2+ children sitting directly inside a lowercase HTML element (e.g. <div><>{"a"}{"b"}</></div>), since the element can hold the children directly; this HTML-element branch only triggers when the single-child check did not already report. Several escape hatches suppress it: a key attribute, any {call()} child (e.g. <>{items.map(...)}</>), a single text-only child whose parent is not itself JSX (content={<>text</>}), and allowExpressions: true which permits <>{expr}</>. False positive: a single-child fragment kept intentionally to widen the return type to ReactNode or to keep a conditional symmetric (show ? <>{children}</> : null) — confirm only when the wrapper is genuinely redundant.

Fix prompt

Use this once validation confirms the diagnostic is real.

For a single-child fragment, remove the wrapper and return its lone child directly: <><Foo /></> becomes <Foo />, and <div><>foo</></div> becomes <div>foo</div>. For the multi-child-inside-HTML case, drop the fragment and let the element hold the children: <div><>{"a"}{"b"}</></div> becomes <div>{"a"}{"b"}</div>. For an empty <></> or <Fragment />, delete it entirely or replace it with the value it was standing in for; if a single-child wrapper is deliberate (broadening the return type to ReactNode or keeping branches symmetric), enable allowExpressions for the <>{expr}</> case or leave it as-is rather than collapsing. See https://oxc.rs/docs/guide/usage/linter/rules/react/jsx-no-useless-fragment

More Architecture rules from the rules reference:

  • react-doctor/jsx-pascal-case: Rename custom JSX components to PascalCase.
  • react-doctor/jsx-props-no-spreading: List each prop explicitly so consumers can see what's being passed instead of spreading.
  • react-doctor/no-clone-element: Pass children, render props, or Children.map instead of cloning elements with React.cloneElement.
  • react-doctor/no-dark-mode-glow: Use a subtle `box-shadow` with neutral colors for depth, or `border` with low opacity. Colored glows on dark backgrounds are the default AI-generated aesthetic
  • react-doctor/no-default-props: React 19 removes `Component.defaultProps` for function components. Move the defaults into the destructured props parameter: `function Foo({ size = "md", variant = "primary" })` instead of `Foo.defaultProps = { size: "md", variant: "primary" }`.