ReactDOM vs createRoot: Why Did React Change the Way We Render Apps?

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

FeatureReactDOM.rendercreateRoot
Introduced inReact 16React 18
Rendering typeSynchronousConcurrent
PerformanceGoodBetter
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.