Suggest an editImprove this articleRefine the answer for “createRoot() vs render()”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**ReactDOM.render()** (before React 17) uses synchronous (legacy) rendering - React blocks the JS thread until it finishes rendering. **createRoot()** (React 18+) uses concurrent rendering - React can pause, resume, and order renders by priority. **Key point:** `createRoot()` enables automatic batching everywhere (even inside `setTimeout` and promises) and new APIs like `useTransition`, `useDeferredValue`, `useId`, streaming SSR.Shown above the full answer for quick recall.Answer (EN)Image## 1. The main difference | **Feature** | **ReactDOM.render()** (before React 17) | **createRoot()** (React 18+) | |---|---|---| | **Rendering type** | *Synchronous (legacy)* - React blocks the JS thread until it finishes rendering | *Concurrent* - React can pause, resume, and order renders by priority | | **Reaction to updates** | All updates run sequentially, with no priorities | Updates are split into urgent / non-urgent (via `startTransition`, `useDeferredValue`, etc.) | | **Automatic batching (grouping setState)** | Works **only** inside React events | Works **everywhere** - even in `setTimeout`, promises, and async functions | | **Support for new React 18+ features** | No (concurrent capabilities can't be used) | Yes (includes everything: concurrent rendering, Suspense SSR, streaming, etc.) | | **SSR API** | `ReactDOM.hydrate()` | `ReactDOM.hydrateRoot()` | | **Update control (flush, transitions)** | No control | Has `useTransition`, `startTransition`, `flushSync` hooks | --- ## 2. Example before and after React 18 ### Before (React 17) ```javascript import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render(<App />, document.getElementById("root")); ``` This call uses the **old synchronous mechanism**. If the app runs a heavy render, React can't interrupt it, and the UI may "freeze". --- ### After (React 18+) ```javascript import { createRoot } from "react-dom/client"; import App from "./App"; const container = document.getElementById("root"); const root = createRoot(container); // a new "root" root.render(<App />); ``` This approach creates a **Concurrent Root**. Now React can: - pause rendering; - defer "low-priority" updates; - perform automatic batching; - work with `startTransition()` and `useDeferredValue()`. --- ## 3. Behavior when updating state An example with asynchronous code: ### React 17 (the old `render`) ```javascript setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); // there will be 2 separate renders }, 1000); ``` ### React 18 (`createRoot`) ```javascript setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); // one combined render thanks to Automatic Batching }, 1000); ``` React now **merges updates itself** even outside React events (for example, in promises or timers). --- ## 4. Impact on hooks and new capabilities `createRoot()` **includes support** for new React 18 APIs: - `useTransition()` / `startTransition()` - controlling update priority - `useDeferredValue()` - deferred values - `useId()` - stable IDs between the client and the server - `Suspense` for *data fetching* and SSR (streaming, `renderToPipeableStream`) If you use `ReactDOM.render()`, these features **don't work** - React stays in "Legacy Mode". --- ## 5. Compatibility and migration - The old `ReactDOM.render()` **still works**, but is marked as **deprecated**. - Migration is extremely simple - just replace one call: ```javascript - ReactDOM.render(<App />, root); + const root = createRoot(root); + root.render(<App />); ``` - The rest of the code (components, hooks, context, etc.) doesn't need to change. --- ## Summary comparison in one sentence > `ReactDOM.render()` is the old **synchronous** render with no priorities. > > `createRoot()` is the new **concurrent** render, which includes React 18's capabilities: batching, transitions, streaming SSR, and a smooth UI.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.