createRoot

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

createRoot

createRoot is the method introduced in React 18 that replaces the older ReactDOM.render method. It is the modern entry point for rendering a React application in the browser.

The Old Way (React 17 and earlier)

Before React 18, you initialized an app by passing the React element and the DOM container to ReactDOM.render.

// ❌ Legacy Mode (React 17)
import ReactDOM from 'react-dom';
import App from './App';

const container = document.getElementById('root');

// The render method takes both the App and the Container
ReactDOM.render(<App />, container); 

This legacy approach had a major flaw: React had to pass the container into the render function every single time there was an update at the root level, making it difficult for React to manage internal state related to that specific root container.

The Modern Way (React 18+)

createRoot separates the creation of the React root from the act of rendering the application.

// ✅ Modern Concurrent Mode (React 18+)
import { createRoot } from 'react-dom/client'; // Note the new /client path
import App from './App';

const container = document.getElementById('root');

// 1. Create the root first
const root = createRoot(container);

// 2. Render the application into that root
root.render(<App />);

Why was createRoot introduced?

createRoot is not just a syntax change; it is the switch that enables Concurrent Features in React 18.

If you use the legacy ReactDOM.render, your application runs in “Legacy Mode,” which behaves exactly like React 17.

By using createRoot, you opt into “Concurrent Mode,” which unlocks powerful new features:

  1. Automatic Batching: In React 18, all state updates (even those inside setTimeout, Promises, or native event handlers) are automatically batched together to prevent unnecessary re-renders. This is only enabled if you use createRoot.
  2. Transitions: The useTransition and useDeferredValue hooks allow you to mark certain state updates as “non-urgent”, keeping the UI responsive during heavy rendering.
  3. Suspense Improvements: Better integration with architectural patterns like streaming Server-Side Rendering (SSR).

Unmounting

If you ever need to completely destroy a React tree and clean up all of its event listeners (e.g., if React is just a small widget inside a larger non-React application), you can call unmount() on the root object.

root.unmount();

Interview Questions

Q: What is the difference between ReactDOM.render and ReactDOM.createRoot?
A: ReactDOM.render is the legacy API used in React 17 and below. createRoot is the new API introduced in React 18 that fundamentally changes how React renders under the hood, enabling Concurrent Mode, Automatic Batching, and advanced Suspense capabilities.