If you’ve worked with React for a while, you probably remember this familiar line of code:
ReactDOM.render(<App />, document.getElementById("root"));
But starting from React 18, you’ll see a new approach:
import { createRoot } from "react-dom/client";const root = createRoot(document.getElementById("root"));root.render(<App />);
So the obvious question is:
👉 Why did React introduce createRoot and move away from ReactDOM.render?
Let’s break it down simply.
What is ReactDOM.render()?
ReactDOM.render() was the traditional way to render a React application into the DOM.
Example (Before React 18)
import ReactDOM from "react-dom";import App from "./App";ReactDOM.render(<App />, document.getElementById("root"));
How it worked
- React rendered the entire UI synchronously
- Updates happened immediately
- Simple and easy, but limited for performance optimizations
What is createRoot()?
createRoot() is the new rendering API introduced in React 18.
Example (React 18 and above)
import { createRoot } from "react-dom/client";import App from "./App";const root = createRoot(document.getElementById("root"));root.render(<App />);
How it works
- Enables Concurrent Rendering
- React can pause, resume, or abandon renders
- Makes apps smoother and more responsive
Why Did React Introduce createRoot()?
The change was made to support modern React features.
Key reasons:
1. Concurrent Rendering
React can:
- Work on multiple UI updates at the same time
- Prioritize important updates (like user input)
- Delay less important renders
This was not possible with ReactDOM.render().
2. Better Performance
With createRoot:
- Large UI updates don’t block the main thread
- The app feels more responsive
- Smooth animations and transitions
3. Foundation for New Features
Many React 18 features only work with createRoot:
startTransition- Automatic batching
- Streaming server-side rendering
- Suspense improvements
What Happens If You Still Use ReactDOM.render()?
- It still works, but:
- Runs React in legacy mode
- You won’t get React 18 performance benefits
- You may see warnings in future versions
👉 React recommends migrating to createRoot.
Key Differences at a Glance
| Feature | ReactDOM.render | createRoot |
|---|---|---|
| Introduced in | React 16 | React 18 |
| Rendering type | Synchronous | Concurrent |
| Performance | Good | Better |
| Supports new features | ❌ No | ✅ Yes |
| Future-proof | ❌ | ✅ |
Should You Migrate?
✅ Yes, if:
- You’re using React 18
- You want better performance
- You plan to use new React features
Migration is simple and usually requires changing just a few lines.
Final Thoughts
The shift from ReactDOM.render() to createRoot() is not just a syntax change —
it’s a major architectural upgrade in how React handles rendering.
Even though the old way still works, createRoot is the future of React.
Small change in code, big improvement in performance.