How to Enable Concurrent Mode in React
This article explains how to transition your application to React’s concurrent rendering model. You will learn how to upgrade your project to React 18, replace the legacy rendering API with the new root API to unlock concurrent capabilities, and start utilizing concurrent features like transitions to improve your application’s performance.
Understanding Concurrent React
In React 18, the development team shifted from an all-or-nothing “Concurrent Mode” to a system of opt-in “Concurrent Features.” Instead of putting the entire application into a different mode, concurrency is enabled under the hood when you upgrade to React 18 and adopt the new root API. This allows you to use specific concurrent features gradually without breaking existing code.
Step 1: Upgrade to React 18
To use concurrent features, you must first update your React dependencies to version 18 or later. Run the following command in your project terminal:
npm install react@latest react-dom@latestIf you are using TypeScript, you should also update your type definitions:
npm install @types/react@latest @types/react-dom@latestStep 2: Switch to the New Root API
Upgrading the package version is not enough to enable concurrent
rendering; you must also update your application’s entry point. React 18
introduces createRoot, which replaces the legacy
ReactDOM.render API.
Legacy Root API (Before)
In React 17 and earlier, the entry point (usually
index.js or main.jsx) looked like this:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));New Root API (After)
To enable concurrent features, update your entry point to use
createRoot:
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);Using the createRoot API automatically enables
concurrent rendering out of the box for updates that opt into it.
Step 3: Use Concurrent Features
Once you have adopted the new root API, your application runs on the concurrent renderer. You can now start using concurrent features to keep your UI responsive during heavy updates.
Marking Updates as Transitions
The most common concurrent feature is the useTransition
hook. This hook allows you to mark non-urgent state updates as
“transitions,” telling React that it can interrupt the rendering of
these updates if a more urgent event (like a keystroke or click)
occurs.
Here is how to implement useTransition:
import React, { useState, useTransition } from 'react';
function SearchResults() {
const [isPending, startTransition] = useTransition();
const [searchQuery, setSearchQuery] = useState('');
const [filteredList, setFilteredList] = useState([]);
const handleChange = (e) => {
// Urgent update: Show the typed input immediately
setSearchQuery(e.target.value);
// Non-urgent update: Wrap in startTransition
startTransition(() => {
// React can pause rendering this list if the user types another character
setFilteredList(filterLargeDataset(e.target.value));
});
};
return (
<div>
<input type="text" value={searchQuery} onChange={handleChange} />
{isPending && <p>Updating list...</p>}
<List items={filteredList} />
</div>
);
}By upgrading your packages, switching to the createRoot
API, and implementing hooks like useTransition or
useDeferredValue, you successfully adopt and utilize
Concurrent React.