oxlint-plugin-react-doctor
0.9.18 · 12 Oct 2026SEE LICENSE IN LICENSE1.4M / weekRepositoryHomepagenpmAtom feed
Latest releases
All 65 releases- 0.9.x · latest line
0.9.18
12 Oct 2026- deprecated
Stop reporting the core SafeAreaView export as removed. It remains implemented even where it is deprecated.
Match API Platform subscription IDs to the provider's resource-and-IDs unsubscribe contract.
Do not infer React hooks from relative helper imports in Angular component classes. Continue to check React and React ecosystem imports.
Patch Changes
Match API Platform subscription IDs to the provider's resource-and-IDs unsubscribe contract.
Do not infer React hooks from relative helper imports in Angular component classes. Continue to check React and React ecosystem imports.
Do not classify a local state transition as a prop-driven adjustment when its only prop dependencies are called notifications. Keep checks for prop values used in guards, results, or reset dependencies.
Do not recommend lazy state initialization for cheap primitive toString calls, including numeric React Native Dimensions values. Keep warnings for unproven receivers and nested expensive calls.
Report inaccessible parent click actions when descendant handlers stop keyboard-generated clicks from reaching them.
Match listener cleanup when both branches of conditional options have the same capture value. Keep warnings for differing capture values, changed options, and missing cleanup.
Recognize exhaustive listener-removal loops extracted into a synchronous helper when the cleanup only invokes that helper.
Add the opt-in
--scope contextualreporting mode. Selected rules report existing findings when their owning function, JSX element, or file changes. Other rules retain line filtering. Support deletion-only edits, staged scans, untracked files, and separate result-cache entries while preserving existing scope defaults and diagnostic locations.Preserve count-based placeholder identity through a local array before mapping wrappers.
Preserve numeric placeholder-loop identity through local key aliases, including constant-prefix keys. Continue reporting index aliases for loops over array data.
Keep browser reads in helpers defined inside React effects out of server-render diagnostics. Preserve warnings for render callbacks and shadowed effect functions.
Do not classify zero-argument effect notifications as state payloads sent to a parent. Continue to report callbacks that pass local state.
ESLint adapter now respects rule
requiresgates. Rules that require capabilities the project doesn't have (likessrorreact-router:8) are now correctly skipped when capabilities are declared, matching the CLI behavior. Fixes false errors on dependency bumps when using the ESLint adapter with explicit capabilities.Fix
async-defer-awaitwarnings on compound guards that compare function parameters with mutable state after an await. Keep these checks after the await so they can detect stale responses. Fixes #1895.effect-needs-cleanup: accept Promise timer that resets its own handle in callback
Fixes #1882. The rule no longer flags a timer created in a Promise callback when the timer's own callback resets the handle to
nullorundefined. This is safe because the timer has already fired when the reset happens, so no live handle is lost.Recognize stable functions rendered as JSX components in the same file, including components that return imported exhaustive matchers. Preserve warnings for mixed utility exports, shadowed JSX names, and reassigned bindings.
Accept observer cleanup after tuple loops and a single animation-frame retry chain when cleanup disconnects the observer and cancels the pending frame. Require observer cleanup on every path and keep target-specific
unobserve()checks.Recognize JSX handlers passed to stable local dispatchers with an explicit React return type. Keep reporting callback registries with unknown or non-rendering return types.
Use constant Boolean initializers before treating numeric-looking JSX guard names as numbers. Preserve warnings for mutable bindings, destructuring defaults, and numeric values.
Require root route error boundaries only for data routers, since declarative useRoutes configurations do not use data-router error handling.
Recognize legacy React.createClass components so render callbacks retain their instance this instead of being treated as function components.
Accept direct anchor children owned by an imported Next Link component, including the legacy Link child API.
Allow state updater callbacks to reassign their local parameter while still reporting writes to prior-state properties and captured values.
Respect the installed or declared React Native version before reporting removed AsyncStorage and WebView exports. Reuse package-version resolution and track manifests for diagnostic cache invalidation.
- deprecated
Stop reporting the core SafeAreaView export as removed. It remains implemented even where it is deprecated.
Restrict App Router path checks to the project app or src/app directory so nested Pages Router paths do not trigger App Router rules.
Recognize optional-chain and TypeScript-wrapped response status guards before fetch body reads.
Avoid treating promise-returning query APIs as array find calls. Keep reports for known arrays and known predicates.
Recognize static import and require paths wrapped in TypeScript assertions, while retaining warnings for dynamic paths inside those wrappers.
Preserve state used by a render-phase throw, including Suspense promises and errors, instead of recommending a ref.
Recognize either global timer-clear API as releasing a matching timeout or interval handle, including exhaustive retained timer collections.
Allow author-provided accessible names on the tooltip role. Preserve naming restrictions on roles that prohibit them and warnings for unsupported tooltip states.
Skip missing image sizes advice when next/image explicitly disables optimization, since that path does not generate responsive source candidates.
A native wrapping or associated label can give a control its accessible name through its title. Recognize that name while keeping warnings for empty labels, unrelated labels, and custom wrappers.
A returned scalar formatter can use JSX only when its scalar input is null. React component props do not follow that path. Exclude these formatters while keeping warnings when JSX is reachable for normal props, a reassigned parameter, or another return path.
Avoid missing-key warnings for JSX arrays returned as data by module-level object factories with no local use. Keep warnings for component and render methods, local factory uses, and arrays rendered directly as children.
A class render helper can receive indices from a numeric Array.from placeholder list. Accept these keys only when every visible use proves that placeholder source and the helper does not escape. Keep warnings for mutable data lists and unknown callers.
A focusable action revealed by group hover also becomes visible when it receives keyboard focus. Accept its own focus or focus-visible opacity reveal when that reveal covers the hover scope. Keep warnings for hidden, invisible, non-focusable, and mismatched-scope controls.
An updater may copy each state element before a local helper changes those fresh copies. Track that ownership through helper parameters and for-of loops. Keep warnings for shared objects, nested shared fields, replaced elements, and aliases that add shared values.
An icon button with a screen-reader-only label is not a text button for visual padding. Ignore hidden label text, but keep visible text and not-sr-only overrides in the check.
A stable local factory that returns a component or forwardRef component is a valid component export. Inspect the factory return paths and keep warnings for mixed returns, reassigned factories, and unknown factory outputs.
Report array-index keys passed as React cloneElement overrides, including imported aliases and static computed keys.
Allow updater callbacks to mutate a local container when both branches of its conditional initializer create a fresh container. Continue reporting mutations of prior state and shared collections.
Ignore unreachable fresh fallbacks inside a controlled-state selection when the value type excludes null.
Use the properties read by a resolved local helper when checking object argument dependencies.
Accept positional keys for immutable arrays of identical literal placeholders. Keep checks for distinct values, records, spreads, and mutated arrays.
Detect fresh cleanup callbacks through local imported wrappers of DOM event listener APIs.
Track subscriptions pushed into arrays that already contain other owned handles.
Do not classify paired Layer.extend lifecycle methods as React event handlers.
Recognize deterministic lazy ref initialization through an immediately preceding local assignment. Check the resolved value for non-deterministic initialization hidden by aliases.
Avoid parent-notification warnings when a local memoized loader only reads props and updates local state. Keep warnings for actual parent callback calls, including asynchronous and direct callback wrappers.
Recognize named functions passed to React memo and forwardRef as render scopes in rules-of-hooks, including nonstandard internal names. Keep conditional and nested hook checks active.
Recognize object URL cleanup returned on every path after URL creation, including effects that return early before they allocate a URL.
Prevent boolean-toggle cleanup analysis from crashing when an effect omits its dependency array. Preserve the existing toggle diagnostic and functional-update exemption.
Follow guarded observer setup helpers invoked by effect-owned listeners.
Recognize loading-set resets paired with cancellation of owned request-map entries.
Recognize react_ujs useContext and useContexts as component registration methods rather than React hooks. Support stable CommonJS and ES module bindings.
Do not classify an imported use-prefixed function as a React hook when its resolved implementation only returns static data.
Accept positional keys for plain text rows from string splitting and Boolean filtering. Keep checks for stateful children, unknown split methods, and changed token arrays.
Recognize portal readiness state after DOM container discovery.
Accept index keys for identical map slots that ignore the item and collection values and use the index only as a key. Keep warnings when output depends on an item or an indexed record.
Recognize fresh const aliases of effect cancellation guards after await. Keep warnings when a snapshot was captured before suspension or another await can make it stale.
Recognize primitive cumulative labels in stateless index-keyed rows.
Accept positional keys for Array.from slots whose count comes from a property or expression. Keep checks when the index reads external records or the source has record entries.
Detect unstable nested components created inside React forwardRef and memo render callbacks, including import aliases and TypeScript wrappers.
Recognize request ownership predicates and loading resets on proven view, close, and unmount paths. Keep warnings when an invalidated request can leave the loading flag set.
Keep React hook ordering checks out of files that use a proven non-React JSX runtime. Mixed React files retain the checks.
Recognize object URLs retained in React refs when replacement and unmount both revoke the owned value.
Recognize clearing the state handle of an object URL after revocation.
Follow synchronous cleanup helpers that invoke a retained listener disposer on unmount.
Do not treat directly returned component functions as JSX rendered by their factory. Keep detecting direct component calls and executed render callbacks.
Avoid cleanup warnings for local functions and state setters named setInterval or setTimeout. Require a global timer or a matching Node timers import before classifying these calls as timer allocations.
Recognize the stable send result of XState React v1 useService when its interpreter is a module singleton.
0.9.17
5 Oct 20260.9.16
4 Oct 2026Avoid sequential-await warnings when local helpers read the same cache entry or delegate to the same imported operation with matching stable arguments. Follow bounded imported helpers to guarded, module-owned Map/WeakMap caches keyed by unchanged function parameters, with dependency fingerprints for cache invalidation. Preserve warnings for distinct imported operations sharing an input, and bound the diagnostic's parallelization advice.
Keep diagnostics when a helper computes a cache key with an unknown call or property read. These values can change between calls.
Recognize convergent last-item equality guards in no-self-updating-effect, including literal tail replacements and appends with tail-preserving deferred trims.
Avoid no-derived-state false positives when custom hooks return draft state setters through immutable aliases.
Patch Changes
Avoid sequential-await warnings when local helpers read the same cache entry or delegate to the same imported operation with matching stable arguments. Follow bounded imported helpers to guarded, module-owned Map/WeakMap caches keyed by unchanged function parameters, with dependency fingerprints for cache invalidation. Preserve warnings for distinct imported operations sharing an input, and bound the diagnostic's parallelization advice.
Keep diagnostics when a helper computes a cache key with an unknown call or property read. These values can change between calls.
Recognize convergent last-item equality guards in no-self-updating-effect, including literal tail replacements and appends with tail-preserving deferred trims.
Avoid no-derived-state false positives when custom hooks return draft state setters through immutable aliases.
Disable
require-pnpm-hardeningby default; enable it explicitly throughruleswhen wanted. Describe await parallelization as a conditional opportunity, preserving ordering, resource limits, and error semantics. Recognize local Promise.all/allSettled collectors and stop describing async array callbacks as sequential.Fix cache/navigation binding resolution and unsafe mutation parallelization (issue #1810)
server-cache-with-object-literal: Properly resolve React.cache imports through aliases and check all argument positions for fresh objects/arrays. Shadowed or non-React cache functions no longer trigger false positives.
nextjs-no-redirect-in-try-catch: Recognize Next.js
unstable_rethrow(error)as a valid error forwarding pattern, suppressing the diagnostic when the caught error is correctly rethrown.server-sequential-independent-await and async-parallel: Detect mutating HTTP requests (POST, PUT, PATCH, DELETE) and preserve their ordering, preventing incorrect parallelization suggestions for operations that must run sequentially.
Fix
effect-needs-cleanupfalse positive for React 19 callback ref cleanup returns. React 19 callback refs can return cleanup functions with the signature(node: T | null) => void | (() => void). The rule now correctly handles cases where cleanup is only returned after resource usage (e.g., afterResizeObserver.observe()), allowingvoidreturns on the null branch.Resolve local Hook-shaped object methods before applying React Hook namespace heuristics, including inspection dispatchers and useEffectEvent.
Preserve Hook diagnostics for unresolved invoked callbacks and bound Hook aliases, while resolving proven local callbacks at each call site.Avoid display-name diagnostics for data factories that return descriptors containing JSX icons.
Preserve anonymous-component diagnostics for proven array maps and React useMemo callbacks that return render output.
Recognize effect-owned timer replacements that clear the previous handle before assignment and release the final timer during teardown.
Respect Solid JSX applicability in handler naming, DOM property, and module-scope helper advice while preserving React diagnostics in mixed-runtime files.
0.9.14
12 Sep 2026Upgrade oxlint to 1.81 and oxc-parser to 0.148.
Avoid
effect-needs-cleanupdiagnostics for owned chained timers, guarded post-await timers, and listeners released through an abort handler.Fix an
async-defer-awaitfalse positive on exactliveandisLiveliveness guards without exempting unrelated names that only contain the same text.
Patch Changes
Upgrade oxlint to 1.81 and oxc-parser to 0.148.
Avoid
effect-needs-cleanupdiagnostics for owned chained timers, guarded post-await timers, and listeners released through an abort handler.Fix an
async-defer-awaitfalse positive on exactliveandisLiveliveness guards without exempting unrelated names that only contain the same text.Fix false positive in
nextjs-no-side-effect-in-get-handlerwhen locally-builtHeadersobject is passed to a same-file helper that mutates it.The rule now transfers locally-created response object safety through the exact same-file helper call. Calls that pass external state to the same helper remain reportable.
Fixes #1757
Speed up large-repository scans: reuse warm oxlint worker processes across projects, overlap project discovery with linting, and trim rule hot paths (2.4–5.5x faster wall-clock on the large-repo corpus).
Stop reporting local service
.use()methods as React hooks. Preserve diagnostics for React namespace calls, including aliases and CommonJS imports.Only recommend
setAnimationLoopwhen a recursive animation frame callback renders through a known Three.js renderer. Leave independent 2D canvas and DOM loops alone, including files that also import Three.js.respect "use no memo" directive in react-compiler-no-manual-memoization rule
When a function or module has a React Compiler opt-out directive, the compiler skips optimization, so manual memoization can still be necessary. The rule now respects
"use no memo", its"use no forget"alias, and local components passed tomemo.Fixes #1749
Exempt magic-link delivery mutations from
query-mutation-missing-invalidationwhile keeping generic send, notification, and email mutations reportable.Retire 33 low-value rule IDs while keeping them registered as silent compatibility entries. Make 26 cleanup, migration, performance, and security-review rules opt-in. Existing rule configurations still load; default scans no longer report these recommendations as defects.
0.9.13
2 Sep 2026Upgrade the Oxc parser and Oxlint runtime while preserving hard failures for broken JS plugins.
Keep ESLint presets on React Doctor's curated low-noise rule behavior and honor configured capabilities when a rule declares
disabledWhen, including suppressing manual-memoization diagnostics for React Compiler projects.Keep the interactive score header intact in narrow split views and invalidate locally stale scan results when rule implementations change.
Report standalone Three.js render loops that use
requestAnimationFrameinstead of the renderer-managedsetAnimationLoopAPI.Include standalone Three.js, supported React framework, Remotion, and React Three Fiber ecosystem packages in automatic workspace project discovery.
Patch Changes
Upgrade the Oxc parser and Oxlint runtime while preserving hard failures for broken JS plugins.
Keep ESLint presets on React Doctor's curated low-noise rule behavior and honor configured capabilities when a rule declares
disabledWhen, including suppressing manual-memoization diagnostics for React Compiler projects.Keep the interactive score header intact in narrow split views and invalidate locally stale scan results when rule implementations change.
Report standalone Three.js render loops that use
requestAnimationFrameinstead of the renderer-managedsetAnimationLoopAPI.Include standalone Three.js, supported React framework, Remotion, and React Three Fiber ecosystem packages in automatic workspace project discovery.
Avoid
artifact-env-leakfalse positives from vendored source-map content and intentionally public token names.Fix
rn-no-raw-textfalse positives in components that return only direct<fbt>or<fbs>elements.Classify fragment returns that contain only translation elements and static text as text-producing components.
Prevent
rn-no-raw-textreports for<fbt>content passed through verified React Native text wrappers.Prevent stack overflows while resolving deeply nested local function references. React Doctor now stops following a reference chain after a bounded number of steps instead of aborting the lint scan.
Fix a
rerender-state-only-in-handlersfalse positive when a member hook consumes state.Avoid false positives for loading resets in
finally, animation duration utilities, and string message substring searches.Fix
js-set-map-lookupsfalse positives for substring checks on values returned by the globalStringconstructor.Run
test-noiserules in ambiguous product-named directories such astools,demo, andmigrationswhen they are below a recognized application source root. Explicit test surfaces and root-level tooling or example directories remain excluded.Ignore browser-global names in TypeScript-only positions so interface and type property keys are not reported as unsafe module-scope runtime access.
Use the nearest workspace root when detecting Fast Refresh ownership so nested checkouts keep the correct rule coverage.
Stop recommending
flatMapas a guaranteed performance improvement for.map().filter(Boolean). The rule now suggests a single-passreduceorfor...ofrewrite only for measured hot paths.Improve repeated effect analysis and deeply nested JSX performance, preserve derived-state detection through transparent TypeScript wrappers, and upgrade Oxc parser and linter dependencies.
Make React cleanup a first-class part of React Doctor with diagnostics for complex React functions and repeated JSX composition. Keep whole-project unused file, export, type, dependency, and import-cycle analysis as explicit opt-in rules while removing the separate Deslop packages, experimental language server, and IDE extensions.
Add component-composition and correctness rules for shadcn, Radix UI, Base UI, React Aria, TanStack Table, and TanStack Virtual behind six new project capabilities (
shadcnfromcomponents.json; the rest from their package dependencies). Dialog surfaces that render no title part and carry no accessible name are reported across all three libraries (shadcn DialogContent/SheetContent/AlertDialogContent/DrawerContent, Radix Dialog.Content and AlertDialog.Content, Base UI Dialog.Popup and AlertDialog.Popup). Icon-sized shadcn Buttons with no accessible name, shadcn FormItem fields wrapping a FormControl without a FormLabel, and Base UI Field.Root controls without a Field.Label are reported as unlabeled. Raw Input, Textarea, and Button controls placed directly inside shadcn InputGroup are reported in favor of its InputGroupInput, InputGroupTextarea, and InputGroupAddon parts, and presence-onlydata-[selected]:/data-[disabled]:Tailwind variants on command items are reported because cmdk renders both attributes as"true"or"false". TanStack Form submit handlers that call the form'shandleSubmitwithoutevent.preventDefault()are reported because the browser still performs a native full-page submission. Tabs triggers provably inside the root without the list part are reported for shadcn, Radix, and Base UI; the existingshadcn-tabs-trigger-requires-listrule is now enabled by default for shadcn projects through the capability gate and no longer risks false positives on extracted trigger subcomponents. React Aria Dialogs without a Heading or aria-label are reported as unnamed. TanStack Tabledata/columnsoptions that provably get a new array identity every render (inline literals, render-scoped const arrays, fresh??fallbacks, inline.filter()/.map()transforms) are reported for rebuilding row and column models each render and looping auto-reset features, and elements measured by TanStack Virtual'smeasureElementwithout adata-indexattribute are reported because the virtualizer drops the measurement.Avoid cleanup false positives for callback refs, observer iteration, and effect-local stored disposers.
Dependency tracking · free for 3 projects
Know when your own dependencies move
oxlint-plugin-react-doctor published 65 releases in the last 12 months. Inlinr folds the routine ones into a line and keeps the few that need you.
Advisories reach you
An email when a critical or high advisory affects a project, before the next install.
Upgrades checked first
Peer ranges, Node, ESM-only and types changes read before you bump.
Only what matters
Majors and breaking notes stay; patches and sibling bumps fold into one line.
Registry facts last checked 22 Oct 2026. Releases and advisories last read 22 Oct 2026.