Use when working on React 18 guidance for ^18 projects, root setup, concurrent rendering, StrictMode, or 17→18/18→19 upgrades. Not for ordinary application logic. Remains a separate React 18 route; pair with `dhpk-react-19-notes` for 18→19 changes and `dhpk-nextjs-15-5-notes` or `dhpk-nextjs-16-notes` for Next integration. Output: migration traps and verification gates.
Installs into .claude/skills of the current project.
Are you the author of Dhpk React 18 Notes?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/hmj1026-dhpk-react-18-notes)
---
name: dhpk-react-18-notes
description: "Use when working on React 18 guidance for ^18 projects, root setup, concurrent rendering, StrictMode, or 17→18/18→19 upgrades. Not for ordinary application logic. Remains a separate React 18 route; pair with `dhpk-react-19-notes` for 18→19 changes and `dhpk-nextjs-15-5-notes` or `dhpk-nextjs-16-notes` for Next integration. Output: migration traps and verification gates."
metadata:
dhpk-invocation-class: implicit-eligible
---
# React 18 — concurrent-rendering baseline
React 18 (March 2022) shipped the concurrent renderer. Its features are
opt-in per update, unlocked by adopting the new `createRoot` API.
> Family routing and the React/Next compatibility matrix live in
> [frontend-framework-routing.md](references/frontend-framework-routing.md). This module owns
> standalone React 18 language guidance after the family is selected.
---
## Signature features
### `createRoot` / `hydrateRoot` (react-dom/client)
The new root API replaces `ReactDOM.render` and is what turns on all
React 18 features. `ReactDOM.render` still works but warns and runs in a
legacy (non-concurrent) mode.
```js
// Before (React 17)
import { render } from 'react-dom'
render(<App />, document.getElementById('root'))
// React 18
import { createRoot } from 'react-dom/client'
const root = createRoot(document.getElementById('root'))
root.render(<App />)
```
SSR hydration moves from `ReactDOM.hydrate` to `hydrateRoot`.
### Automatic batching
All state updates are now batched — including those inside promises,
`setTimeout`, and native event handlers, not just React event handlers.
Force a synchronous flush with `flushSync` when a DOM read must happen
between updates.
```js
setTimeout(() => {
setCount(c => c + 1)
setFlag(f => !f)
// React 18: one re-render (batched); React 17: two re-renders
}, 1000)
```
### Concurrent features (opt-in)
Enabled per update, not globally:
- `startTransition` / `useTransition` — mark non-urgent updates so urgent
ones (typing) stay responsive.
- `useDeferredValue` — defer re-rendering a value under load.
```js
import { startTransition } from 'react'
setInputValue(input) // urgent
startTransition(() => {
setSearchQuery(input) // non-urgent transition
})
```
### Streaming SSR + selective hydration
`renderToPipeableStream` (Node) / `renderToReadableStream` (web/edge)
replace `renderToString` for streaming; `<Suspense>` boundaries stream and
hydrate selectively.
### New hooks
- `useId` — stable unique IDs matched across server/client (a11y attrs).
- `useSyncExternalStore` — lets external-store libraries subscribe safely
under concurrent rendering.
- `useInsertionEffect` — for CSS-in-JS libraries to inject styles before
layout effects.
---
## Migration traps
Ordered by blocker severity, most severe first.
### 1. Switch the root API to `createRoot`
Until `ReactDOM.render` -> `createRoot` is done, the app runs in legacy
mode and none of the React 18 features (concurrent rendering, batching in
all contexts) are active. `render` also logs a deprecation warning.
### 2. StrictMode double-invokes effects in dev
In development, `<StrictMode>` mounts, unmounts, and remounts each
component once, so effects (and their cleanup) run twice. This is dev-only
(no production effect) but surfaces missing cleanup and breaks code that
assumed a single mount.
### 3. Automatic batching can change assumptions
Code that relied on a re-render between two `setState` calls inside an
async callback now sees a single batched render. Use `flushSync` where a
synchronous flush is genuinely required.
### 4. `react-dom/server` API changes
`renderToString` is discouraged for streaming (move to
`renderToPipeableStream`); `renderToNodeStream` is deprecated.
### 5. TypeScript: `children` no longer implicit
`@types/react` 18 dropped the implicit `children` on `React.FC` — declare
`children` explicitly or type props with `PropsWithChildren`.
---
## What's missing compared to 19
- **No Actions / `useActionState` / `useOptimistic` / `useFormStatus`** —
form-action ergonomics arrive in 19.
- **No `use()` hook** — reading a Promise/Context conditionally is 19.
- **`ref` still needs `forwardRef`** — 19 makes `ref` a plain prop.
- **Document metadata not hoisted** — `<title>`/`<meta>` in components
needs a library (React Helmet); 19 hoists natively.
- **Deprecated APIs still present** — `propTypes`, `defaultProps` (function
components), legacy Context, and string refs still work in 18; 19 removes
them.
---
## When NOT to Use
Not for application business logic. Not for a React 19 project — use
`dhpk-react-19-notes`. Not for generic JS/TS tooling concerns (ESLint config,
typing strategy) — use the `js` module. Not for Next.js framework APIs —
use the `nextjs-*` modules.
## Output
React root/setup or review notes matching React 18's APIs — flag leftover
`ReactDOM.render`/`hydrate` (should be `createRoot`/`hydrateRoot`), effects
with no cleanup (StrictMode double-invoke), or async `setState` sequences
that assumed unbatched renders.
## Verification
- Confirm the project runs 18 (`package.json` `react`/`react-dom` on
`^18`, or check `node_modules/react/package.json`).
- Note React 18.2+ is the minimum Next.js 16 supports.
- Cross-check any cited API against Context7 `/reactjs/react.dev`.
---
## Cross-references
- `skills/dhpk-react-19-notes/SKILL.md` — the upgrade target
(Actions, `use()`, ref-as-prop, document metadata, removed legacy APIs)
- `skills/dhpk-nextjs-15-5-notes/SKILL.md` and
`skills/dhpk-nextjs-16-notes/SKILL.md` — pair a Next.js
major with this React major cross-stack
- `modules/js/skills/` — the generic JS/TS ESLint + typing tooling module