How does React Doctor find hard-to-change code?
React Doctor finds React code that makes future changes slower or riskier. Complexity and repeated JSX checks run by default. Six optional rules add whole-project import graph analysis.
Complex React components and hooks
The react-doctor/no-high-complexity-react-function rule measures control flow in functions identified as React components and custom hooks. It reports a function when cyclomatic or cognitive complexity exceeds 15.
Each diagnostic includes three measurements:
- Cyclomatic complexity: the number of reachable control-flow paths
- Cognitive complexity: the reading cost added by branches and nesting
- Maximum nesting depth: the deepest control-flow level in the function
React Doctor excludes ordinary JavaScript functions and nested callback complexity from the owning component. A reported function should become easier to understand when you extract independent branches into components or hooks.
Repeated JSX structures
The react-doctor/duplicate-jsx-subtree check compares JSX structure across the project. It normalizes data leaves, such as labels and local variable names, while preserving component composition and expression behavior.
React Doctor reports substantial repeated trees instead of every matching element. A finding includes:
- Every matching location
- The lexical composition path for the primary copy
- The copy count and tree node count
- The estimated repeated line count
Keep copies separate when the similarity is incidental or the interfaces are likely to evolve independently. Extract a component when the copies represent the same UI concept.
Results in partial scans
Changed and staged scans check complexity in the selected source. Duplicate JSX analysis compares the full source corpus, then reports families connected to selected files or lines.
This catches a new copy of existing JSX without flooding the report with unchanged findings. Pull request scans use the same baseline comparison as changed scans.
Optional whole-project graph rules
Six project graph rules are available for targeted cleanup. They are disabled by default and run only during full scans. Partial and baseline scans skip them because those scopes cannot prove whole-project reachability. The available rules are:
react-doctor/unused-file: finds source files that no discovered entry point can reachreact-doctor/unused-export: finds value exports with no in-repository consumerreact-doctor/unused-type: finds type exports with no in-repository consumerreact-doctor/unused-dependency: finds production dependencies with no detected usereact-doctor/unused-dev-dependency: finds development dependencies with no detected usereact-doctor/circular-dependency: finds runtime import cycles with top-level binding access
Enable only the checks you want in doctor.config.json:
{
"$schema": "https://react.doctor/schema/config.json",
"rules": {
"react-doctor/unused-file": "warn",
"react-doctor/unused-export": "warn",
"react-doctor/unused-type": "warn",
"react-doctor/unused-dependency": "warn",
"react-doctor/unused-dev-dependency": "warn",
"react-doctor/circular-dependency": "warn"
}
}Each rule page includes its detection boundary, false-positive checks, and a before-and-after example. A Maintainability category override does not activate these rules. The explicit rule entry sets each enabled rule's severity.