React Concurrent Mode - Revisited
Author

Date

Book a call
Concurrent Mode was announced about a year ago and is still an experimental feature that lets our app remain responsive in different network conditions and based on different device capabilities. Without any further ado, let's discuss the new features and concepts introduced in Concurrent Mode. We will discuss these features in the context of React and React apps:
1. Interruptible Rendering
Normally in React, if rendering begins and a user event occurs (like clicking a button), React will first complete the previous render and then process the user event. So, React uses blocking rendering, which can create some performance issues.
Concurrent Mode introduces the concept of interruptible rendering, so if rendering has started and a user event happens in between, React will stop the previous rendering, process the user event first, then continue the remaining part of the previous rendering. Concurrent Mode uses Time Slicing for interruptible rendering.
2. Data Fetching With Suspense
It works on a Render as you Fetch approach, which means that React starts loading the data without waiting for the component to load. Both the data and component start loading in parallel.
Here, we wrap our MySuspenseImage
component in a Suspense
component, which provides the fallback component until the image is loaded. We try to render MySuspenseImage
even when imageData
is not yet loaded. This makes MySuspenseImage
suspend as a promise
is thrown. The Suspense
component catches the promise
and shows the fallback component in the meantime. As soon as the promise
resolves, it re-renders the image component. If any errors occur during data loading, they can be handled using the ErrorBoundary
component.
3. SuspenseList
Suppose a page has multiple API calls. It’s likely their responses won’t come in the order required by the UI, which affects user experience. We can chain promises to maintain order, but that adds complexity.
SuspenseList
solves this by providing a controlled loading sequence for different parts of the page. It wraps multiple Suspense
components and uses the revealOrder
property to control the order of reveal: 'forwards'
, 'backwards'
, or 'together'
.
We can also control the number of loading indicators using the tail
property, which can be 'hidden'
or 'collapsed'
. When tail
is 'collapsed'
, only one loader is shown at a time.
In the example (shown in the GIF), with revealOrder='forwards'
and tail='collapsed'
, first the user image is rendered, then user details, and finally user comments. This ensures smooth, sequenced UI loading. All async processes begin together, but the reveal order is controlled visually via SuspenseList
.
4. useTransition Hook
Suppose you're on a fast connection and click your profile. You may transition instantly and see a loader for just 200ms, causing UI flicker. This can be fixed with complex logic, but the useTransition
hook simplifies it.
It lets you wait on the current screen while new data loads, then transition smoothly.
The useTransition
hook returns two values:
When a user clicks to navigate, React prepares the update in a separate branch while remaining on the current screen. If data loads quickly, it transitions early; otherwise, it waits for the defined timeout, then transitions. This reduces jarring screen transitions and flickering loaders.
You can see that the loader is shown on the previous screen while userDetails
are fetched, then transitions smoothly to the new screen, loading the remaining data.
GitHub project link: https://github.com/Aashishgtbit/concurrent-react-example
References: https://reactjs.org/docs/concurrent-mode-intro.html
Thank you for reading!
Book a Discovery Call
Dive deep into our research and insights. In our articles and blogs, we explore topics on design, how it relates to development, and impact of various trends to businesses.