The most significant update of React 18 comes with concurrent rendering. Concurrency is the ability to execute multiple tasks simultaneously by prioritizing the tasks. This concept is explained nicely by Dan Abramov with a simple analogy of phone calls.
React 18 exposed a few APIs to allow users to have some control over concurrency.
One of them is the startTransition
API,
which indicates that the actions wrapped in startTransition may take time.
Let’s explore in detail the startTransition
API.
Sometimes we come across applications that become unresponsive due to heavy or complex operations.
Consider an example of searching a photo from a large list. When we type the photo name in the search input, we expect the typed character to appear on the screen without any delay. It becomes frustrating when we don’t see the characters quickly and, the first reaction which comes up in our minds is “Ahh, this app is so slow!”
Why is the search a bit laggy?
Let’s see the code.
Whenever the user types a photo name in the search, two different updates need to happen.
First, we save the typed value in the state.
Then, we use the stored value to search for photos.
The first update is an urgent one, to change the value of the input field and display the typed character. The second one is to show the results.
Until React 18, all the updates were treated as urgent. Though the user assumes that showing search results may take time, both the updates would be rendered at the same time. It would block the user from seeing the feedback making it feel a bit unresponsive.
Priorizing updates with the startTransition API to improve user interaction
The new startTransition
API helps to categorize the updates as urgent and non-urgent.
The events like click, select, etc.,
which need an immediate response,
should be treated as urgent ones.
Other updates like displaying search results,
text highlighting,
etc.,
which are not expected to be immediate can be marked as transition or non-urgent.
This can be done by wrapping the transition into startTransition
.
Can we use setTimeout instead of the startTransition API?
We would think of using setTimeout
to delay the search result as below -
Debouncing and throttling are other techniques that could also be used.
Let’s see the advantage of using startTransition
over other options.
Unlike setTimeout
, startTransition
is not scheduled for later.
The function passed to startTransition runs synchronously,
but any updates inside of it are marked as ‘transitions’.
Based on this information
React decides how to render the update.
React starts rendering the updates earlier than if it were wrapped in setTimeout. On a fast device, there would be a little delay between the two updates. Whereas on a slow device the delay would be larger, but the UI would remain responsive.
How to handle the pending transition?
To inform the user about the ongoing background work,
React provides isPending
flag,
allowing us to show a spinner while the user waits.
We can modify our SearchPhotos
component as below to show the spinner -
We found some interesting discussions on the below topics -
To know more about the startTransition API, check out the WG discussion and a quick overview on the behavior of startTransition API.