What is React Concurrent Mode and Why Should You Care?

Published on 10.3.2020

If you’ve been following React’s progress over the past few years, you’ve probably heard about Concurrent Mode. This experimental feature promises to drastically improve the performance of React apps, especially for complex user interfaces. In this post, we’ll introduce you to Concurrent Mode, explain how it improves rendering performance, and show you how to make your UI more responsive with startTransition().


What is Concurrent Mode?

Concurrent Mode is an experimental feature that allows React to work on multiple tasks at once. Rather than blocking the UI while it processes expensive updates, Concurrent Mode lets React pause, prioritize, and interrupt tasks to keep the user interface responsive and interactive.

In traditional React rendering, the entire component tree is updated in a single pass. This can be problematic when you have complex components or slow-running tasks, as it can lead to UI blocking, where the app feels unresponsive to the user.

With Concurrent Mode, React can split rendering tasks into smaller chunks, allowing more important updates (such as user interactions) to be handled first. This results in a more responsive user experience, especially for large applications.


How Does Concurrent Mode Improve Rendering Performance?

The main goal of Concurrent Mode is to improve UI responsiveness. In normal rendering, React performs updates synchronously, meaning that a render can block other updates or interactions from happening at the same time. However, this can be problematic when you have complex components that take a long time to render or expensive computations in the background.

With Concurrent Mode, React can:

  1. Pause and Resume Rendering: If React is working on a rendering task and a higher-priority task comes up (like user interaction), it can pause the current task, handle the higher-priority task, and resume the original task later. This ensures that the app remains interactive, even during heavy rendering tasks.
  2. Prioritize Updates: React can prioritize more important updates (such as user input or screen updates) over less urgent ones. For example, if you are typing in a text input, React will prioritize keeping the input responsive over updating a large list or table.
  3. Avoid UI Jank: In traditional rendering, a long-running task might cause UI jank—where the interface freezes or becomes sluggish while React is busy. Concurrent Mode solves this by breaking the rendering work into small, non-blocking pieces.
  4. Interruptible Rendering: This means that React can interrupt rendering when more important tasks need attention. React doesn’t wait for the entire component tree to finish rendering before allowing other user actions to be processed.

How to Use Concurrent Mode?

Currently, Concurrent Mode is still experimental and not enabled by default in React. To use it, you’ll need to opt-in by using the ReactDOM.unstable_createRoot() API, which enables Concurrent Mode for the entire React tree.

Here’s how you enable it in your app:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

const root = ReactDOM.unstable_createRoot(document.getElementById('root'));
root.render(<App />);

This is a basic example of enabling Concurrent Mode, but keep in mind that it’s still an experimental feature and should be used carefully, especially for production apps.


Making Your UI More Responsive with startTransition()

One of the key features introduced alongside Concurrent Mode is startTransition(). This API allows you to mark non-urgent updates (like heavy computations or background tasks) as lower priority. React will then prioritize updates that are more critical for user interaction, like typing, clicking, or navigating.

What is startTransition()?

startTransition() allows you to defer non-urgent updates. For example, if you’re working with a large list of items and applying a filter, you don’t want React to block the UI while it renders all the filtered items. Instead, you can mark the filtering operation as a transition, which will allow React to keep the UI responsive during the process.

Here’s how you can use it:

import React, { useState, useTransition } from 'react';

function SearchList({ items }) {
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();

  const filteredItems = items.filter(item =>
    item.toLowerCase().includes(query.toLowerCase())
  );

  const handleChange = (event) => {
    const newQuery = event.target.value;
    setQuery(newQuery);

    startTransition(() => {
      // The filtering operation is now deferred
      // React will prioritize this operation lower
      // to keep the UI responsive
    });
  };

  return (
    <div>
      <input 
        type="text" 
        value={query} 
        onChange={handleChange} 
        placeholder="Search..."
      />
      {isPending ? <div>Loading...</div> : null}
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

How Does startTransition() Help?

  • Non-blocking UI: When you type in the search box, the filtering operation is wrapped in a low-priority transition. React will still keep the UI responsive and not block user input, even if the filtering operation is expensive.
  • Faster Updates: Because React prioritizes user input over non-urgent updates, the UI will feel more snappy and responsive. You won’t see delays as React finishes applying the filter or other background tasks.

Why Should You Care About Concurrent Mode?

  1. Improved User Experience: Concurrent Mode allows for seamless, lag-free interactions, even when your app is doing something computationally expensive. If you’re building an app where the UI needs to remain responsive even while data is loading or heavy tasks are processing, Concurrent Mode is a must.
  2. Better Performance: By breaking down large rendering tasks into smaller chunks, React can handle more updates without slowing down the UI. This is particularly important for large-scale apps where performance can become a bottleneck.
  3. Future-Proofing Your App: Although Concurrent Mode is still experimental, enabling it in your app prepares you for future React features and optimizations. As React continues to develop, apps built with Concurrent Mode will benefit from ongoing performance improvements.
  4. Handling Complex UI States: If you’re building complex UIs with a lot of state and asynchronous updates, Concurrent Mode ensures that React can keep track of all of these updates in a non-blocking way. The result? Faster rendering and a smoother user experience.

Conclusion: Why You Should Start Exploring Concurrent Mode

React Concurrent Mode is one of the most exciting advancements in React development, offering a whole new way to handle rendering and user interactions. By allowing React to prioritize important updates and run less important tasks in the background, it opens the door for smoother, faster, and more responsive user interfaces.

While still in experimental stages, Concurrent Mode shows a lot of promise and should be considered for any React app that requires a high level of performance, such as large-scale applications or apps with complex UIs.

As React continues to improve and stabilize Concurrent Mode, it will become an essential tool for developers who want to build faster, more fluid experiences. If you’re working on a new project or updating an existing one, consider giving startTransition() and Concurrent Mode a try to see how much more responsive your UI can be.

Happy coding, and let us know if you have any questions or thoughts on using Concurrent Mode!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *