react-bc-1
automated
confirmed by docs
Not started
ReactDOM.render() is deprecated in React 18 (the app keeps running in legacy React 17 mode) — replace with createRoot().render()
0 files
Session 3fd51510 · generated 2026-09-26 10:19:05 UTC
Rules loaded
Next action
Score the blast radius (calculate_migration_blast_radius).
01Risk & priority
Risk has not been scored yet. calculate_migration_blast_radius scores every file from concrete API evidence (see the severity guide).
02Breaking changes
react-bc-1
automated
confirmed by docs
Not started
ReactDOM.render() is deprecated in React 18 (the app keeps running in legacy React 17 mode) — replace with createRoot().render()
0 files
react-bc-2
automated
confirmed by docs
Not started
ReactDOM.hydrate() is deprecated in React 18 (legacy mode) — replace with hydrateRoot()
0 files
react-bc-3
automated
Not started
act() from react-dom/test-utils is deprecated — import act from 'react' (available from React 18.3)
0 files
react-bc-4
manual
confirmed by docs
Not started
Automatic batching: setState calls in timeouts/promises/native handlers are now batched — may affect code or tests relying on intermediate renders
How to fix Review any tests that assert on intermediate render states inside setTimeout, Promise.then, or native event handlers. Wrap those assertions in act() or use flushSync from 'react-dom' to opt out of automatic batching where needed.
0 files
react-bc-6
manual
confirmed by docs
Not started
Strict Mode now double-invokes effects (mount → unmount → mount) in development to surface side effects
How to fix Audit useEffect, useLayoutEffect, and class lifecycle methods for non-idempotent side effects (network requests, analytics calls, subscriptions). Ensure cleanup functions are implemented so double-invocation does not cause observable problems in development.
0 files
react-bc-7
manual
Not started
ReactDOM.unstable_batchedUpdates is redundant under React 18 automatic batching
How to fix With React 18's automatic batching, explicit calls to unstable_batchedUpdates are no longer needed in most cases. Remove them and verify behaviour. If you need to force synchronous rendering, use flushSync from 'react-dom' instead.
0 files
react-bc-8
manual
confirmed by docs
Not started
ReactDOM.unmountComponentAtNode() is deprecated in React 18 — call root.unmount() on the root returned by createRoot()
How to fix Keep the root returned by createRoot(container) and call root.unmount() instead of unmountComponentAtNode(container). In tests, unmount the root the test created (React Testing Library unmounts automatically).
0 files
react-bc-12
manual
confirmed by docs
Not started
Tests that render with react-dom directly need globalThis.IS_REACT_ACT_ENVIRONMENT = true under React 18
How to fix In the test setup file (e.g. setupTests.js / jest.setup.js), set globalThis.IS_REACT_ACT_ENVIRONMENT = true; so React 18 knows it runs in an act-aware test environment. React Testing Library ≥ 13 sets this automatically for tests that use it.
0 files
03Compatibility
Checked 602 packages via package-lock.json (lockfileVersion 3).
| Package | Requires | Source | Resolution |
|---|---|---|---|
@testing-library/react@12.1.5 | react <18.0.0 | lockfile | auto upgraded to ^14.3.1 in the dependency step |
04Migration plan
No plan yet. generate_migration_plan orders the work (dependencies first, then high-severity changes) and waits for your approval.
05Affected files
11 files
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React, { useReducer } from 'react'; | — |
| 1 | useReducer · react | import React, { useReducer } from 'react'; | — |
| 23 | useReducer · react | const [items, dispatch] = useReducer(itemsReducer, []); | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React, { useState } from 'react'; | — |
| 1 | useState · react | import React, { useState } from 'react'; | — |
| 4 | useState · react | const [name, setName] = useState(''); | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| 3 | Component · react | export default class ItemList extends React.Component { | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React, { useState } from 'react'; | — |
| 1 | useState · react | import React, { useState } from 'react'; | — |
| 7 | useState · react | const [status, setStatus] = useState('idle'); | — |
| 8 | useState · react | const [syncedAt, setSyncedAt] = useState(null); | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| 2 | import react-dom | import ReactDOM from 'react-dom'; | — |
| 5 | render · react-dom | ReactDOM.render( | — |
| 6 | StrictMode · react | <React.StrictMode> | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react-dom | import ReactDOM from 'react-dom'; | — |
| 13 | unstable_batchedUpdates · react-dom | ReactDOM.unstable_batchedUpdates(() => { | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| 2 | import react-dom | import ReactDOM from 'react-dom'; | — |
| 17 | render · react-dom | ReactDOM.render(<Toast message={message} />, host); | — |
| 19 | unmountComponentAtNode · react-dom | ReactDOM.unmountComponentAtNode(host); | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| 2 | import react-dom | import ReactDOM from 'react-dom'; | — |
| 3 | import react-dom/test-utils | import { act } from 'react-dom/test-utils'; | — |
| 3 | act · react-dom/test-utils | import { act } from 'react-dom/test-utils'; | — |
| 13 | act · react-dom/test-utils | act(() => { | — |
| 18 | act · react-dom/test-utils | act(() => { | — |
| 27 | act · react-dom/test-utils | act(() => { | — |
| 28 | render · react-dom | ReactDOM.render(<p>host</p>, container); | — |
| Line | Usage | Source | Rules |
|---|---|---|---|
| 1 | import react | import React from 'react'; | — |
| 2 | import react-dom | import ReactDOM from 'react-dom'; | — |
| 6 | hydrate · react-dom | ReactDOM.hydrate(<App />, document.getElementById('root')); | — |
06Changes
Nothing has been changed — the plan is not approved, and the backend refuses to modify the repository until it is.
07Verification
Verification has not run yet. It runs after the plan is approved and applied: verify_migration checks the installed versions, then runs the repository's own lint, test and build scripts.
08Remaining work
The plan has not been generated yet.
09Metrics
measured
| Files using react | 11 |
|---|---|
| Files with breaking-change evidence | not calculated |
| Files changed on branch | branch not created |
| Steps applied automatically | 0 / 0 |
| Steps completed manually | 0 |
| Steps still open (manual / skipped / failed) | 0 |
| Elapsed session time (wall-clock) | 0 min |
estimate
not measured
10Repository
| Repository | codebase-doctor-sandbox/pantry-list |
|---|---|
| Default branch | main |
| Migration branch | codebase-doctor/react-18.3.1-upgrade |
| Language | javascript |
| Package manager | npm |
| Test framework | jest |
| Lint / test / build | npm run lint · npm run test · npm run build |
| Source files scanned | 13 |
| Rule set | react-17-to-18.json + your migration docs |
| Session | 3fd51510-5cd8-41f8-8271-285c542bb72f |