react concurrent mode. reactjs

What the Concurrent Mode on React Can Do For You

It seems that React is doing it again. Their new Concurrent Mode paradigm is in the books for a release this year.

Remember in February 2019, when we were all hustling to learn Hooks? I do, with fondness. It felt refreshing to finally have a good excuse to move away from Class components and their confusingly named lifecycle methods, streamlining code and enhancing readability. Buzzword this time is Concurrency. So, I gathered all the official documentation and a few examples, and sat down to figure out what it meant for React-based projects.

TL;DR

Concurrent mode introduces a set of tools that will help rethink the way we fetch data and code.

It will also give product teams a chance to join the fun of orchestrating the fetching of data.

Why Concurrent Mode

The best example I’ve found is the filtered list. Picture a long list of entries which takes forever to render. Now imagine that we have a text input field which filters that list. Every time we change the input, React will re-render the component, triggering a redraw of the list. If the list is expensive enough, pretty soon the input field will become laggy and unresponsive because UI libraries will only render one thing at a time: the re-render of the input field will have to wait for the list to be complete.

react concurrent mode explained image 1 - zartis

Up to now we’ve had a couple work-arounds for this:

  1. we can throttle the onChange handler on the input, re-rendering the list only after a certain number of changes, which will free up execution time for our text input,
  2. or we can debounce, meaning that the list only changes when the user is done typing.

Both solutions seem a bit hacky, and all we’re doing is hiding a lag due to a less performant browser behind an unexpected behaviour for an input. Besides, there’s the added downside that on faster applications and machines, where the lag is not noticeable, the input won’t be triggering re-renders whenever the user types a key.

What is Concurrent Mode on React

Enter Concurrent Mode. The aim of this new functionality is to keep React responsive to user interaction and to avoid lag, which boils down to enhancing the end user’s experience.

With concurrency, the component rendering process becomes interruptible: React can choose which update is most important, interrupt the rest, and then come back to finish its job once it’s done; much like how a chef will prioritize awaiting orders.

Suspense

React has also introduced suspense, which takes the Suspense component shipped in  React 16.6 and introduces a new twist: the component can tell React when it’s ready to be rendered. When it is, React will take it out of suspended mode and render it on the page.

So what? Well, first to jump to mind is that we’ll have to rethink how we orchestrate data-fetching. “Loading states” no longer belong in the component, but in the parent component that renders it.

The Concurrent Mode API has a few more tricks up its sleeve. The official documentation is very clear and complete, full of useful examples, but I will quote the ones that stood out.

Suspense boundaries

A Suspense component takes a fallback prop to tell React what to render while its children are suspended, and this can be text or JSX: you might want to replace the suspended component with a spinner or some other visual cue. How we organize Suspense components on a view will affect how loading state is transmitted to the user and the order in which components appear when they come out of their suspended state. Note that Suspense components can also be nested.

[js]<Suspense fallback=’Loading post…’>
<Title />
<Body />
<h4>Comments</h4>
<Suspense fallback=’Loading comments…’>
<Comments />
</Suspense>
</Suspense>[/js]

In this example, a blog post will be suspended until the title and body are ready to be rendered. Once they’re visible, Comments will suspend and show its fallback.

react concurrent mode

Getting the order right

When components are on the same hierarchical level, SuspenseList will tell them what order to appear in. For example, you would want the blog post body to appear before the comments, so we wrap the suspended components in a SuspenseList, which will make sure the sections will appear sequentially.

In this case we’ll set the body to arrive before the title does. Of course, this is not the way we want things to render, so we can set them in a SuspenseList.

reactjs frontend code

The components will come out of suspense sequentially as their data loads.

react concurrent mode

See this example here

 

Transitioning to suspended state

Another sweet addition to the Concurrent Mode API is the hook useTransition, which allows us to transition to a component in suspended state. Say you click a button to view an expensive component. It might be useful to add a spinner and a disabled attribute to the button for a few milliseconds, without triggering a view change, and then transition to the suspended component, therefore dividing the waiting time between the caller and the suspended component. If it comes out of its suspended state early, the component can render in the flow without the need for a fallback.

react functionalities explained by team zartis

See this example here

This is a very useful solution for avoiding views full of suspended components and loading indicators. In fact, the React documentation predicts that useTransition will be very common; one can basically use it in all UI elements that trigger a component suspending (see here).

 

Fetching data as you render

This might be Concurrent Mode’s most interesting addition. We’re all used to fetching data in one of two ways:

  1. in componentDidMount or useEffect, rendering your view’s loading state and then fetching the data, or
  2. in the parent component, which would mean that you render the component once the data is ready.

Suspense allows you to fetch data as you render. Say we’re loading a blog post from your API and you have a body and a comments component. With Suspense you can kick off data fetching as the component starts to render, suspending any content that’s waiting for data to arrive.

table - react data fetching as you render - zartis

 

As you can see in the example, data fetching begins when the Post component is first loaded. As the body and the comments start coming in, their respective views come out of suspense and render in the post.

 

This in turn opens up new possibilities, such as eager loading (see the React documentation about this), where we can try to guess what the user’s next action will be and start fetching accordingly. Straight out of the React docs: we can assume that if a mousedown or mouseover event happens on a router link such as <Link to=”/posts/5” />, the user is probably going to click it, so this would be a good time to start fetching data for a post with id = 5.

 

In conclusion

This is all very exciting. Hooks, as you know, had developers in mind. Concurrent Mode, or at least what we know about it at the present, seems like a good opportunity for product teams to give data loading orchestration a more in-depth analysis: transitions, orchestration of loaders, and what data is relevant for barebones render.

 

We will also have to rethink how components use data, what parts of a component state are most important for rendering, and which ones can be waited for – what people at React call high and low priority state.

 

One final thought is about Error boundaries: if you haven’t implemented them yet, you should. Suspense uses them to alert of any errors encountered in the render and data fetching phases. No more try {} catch {} blocks in API calls, folks.

 

—–

This take on what you could do with the concurrent mode in ReactJS has been prepared by Antonio Reher, who is a Tech Lead at Zartis. Feel free to reach out to us to connect with him or check our other posts on ReactJS HERE!

Share this post

Zartis Tech Review

Your monthly source for AI and software related news