preface

React 18, the next big release of React, adds a new mechanism for ReactConcurrent rendering, dramatically improved React performance and introduced the concepts of time slicing and task prioritization. Here’s the official description:

Concurrent features

React 18 will be the first release to add optional support for concurrent:

  • StartTransition: Allows your UI to remain responsive during an expensive state transition
  • UseDeferredValue: Allows you to delay updates to less important parts of the screen

  • : Allows you to control the order in which loading status indicators (such as the SuspenseList) appear
  • Streaming SSR with Selective Tells: Get your app to load faster and interact with you

This time we’ll take a look at the startTransition API and then share more details about the other features.

startTransition

An overview of the

React 18 adds a new API, startTransition, which is a great way to keep our pages responsive during large screen updates. This API improves user interaction by marking certain updates as “Transitions.” React allows you to provide visual feedback throughout a state change and keep the browser responsive throughout the process.

What problem was solved

Making apps feel smooth and responsive all the time isn’t easy. For example, when a user clicks a button or enters something in an input box, the page will be flooded with updates, causing the page to freeze or hang for a while until the previous update task is completed.

Let’s start with a Demo that uses the current React release version 17.0.2

The React 17.0.2 Demo

It can be found that every time the user enters, we update the value of the input and use this value to update a list of 30,000 items. However, such large screen updates make the page unresponsive and make user input and other user interactions feel slow.

Theoretically, the problem is that there are two different updates that need to take place. The first update is an urgent update that changes the values in the input field, and the second update is a less urgent update that shows the updated list after user input.

// Urgent update: display user input
setInputValue(e.target.value); 
 
// Non-urgent updates: show results
setContent(e.target.value); 
Copy the code

Users usually expect the first update to be more timely, and the second update to be slightly delayed. At work, we often delay updates artificially by using methods such as debounce. Debounce, on the other hand, creates a suboptimal user experience because render cannot be interrupted once it has started, while Concurrent breaks this limitation and allows the render process to be interrupted. React does not block the browser to update the input field when the user presses a key. Instead, ask the browser to update the input and then the Render List. So concurrent mode eliminates the need for React to artificially delay work by relying on Debounce.

Prior to React 18, all updates had no priority and were urgent, which meant that the above two status updates would be rendered at the same time and still block users from getting feedback on their interactions until everything was render ready.

How does startTransition solve this problem

The new API startTransition solves this problem by giving us the ability to mark an update to “Transitions” : Let’s look at another Demo, the same scenario as before, but this time using the as-yet-unreleased version 18 of React.

The React 18.0.0 – alpha Demo

// Urgent update: display user input
setInputValue(e.target.value); 
 
// Mark non-emergency updates as "Transitions"
startTransition(() = > { 
    setContent(e.target.value); 
}); 
Copy the code

Updates wrapped in startTransition are treated as non-urgent updates and are interrupted by other urgent updates. If transition is interrupted by the user, React will stop rendering and render will perform a more urgent rendering update.

How does startTransition work

Described above so much, then we look at the bottom of the startTransition through source code is how to realize the function, I see here is the react in the master (568 dc3532e25b30eee5072de08503b1bbc4f065d) branch on the latest code, It is still being updated.

ReactDOM.createRoot: Enables Concurrent mode

The first step is to enable Concurrent mode, which cannot be enabled for a subtree alone, but should be enabled in reactdom.render () and then usedReactDOM. CreateRoot () to replaceReactDOM. Render (),This enables concurrent mode throughout the structure tree.

startTransition

Scope:This corresponds to the function we passed to startTransition in the demo:

() => { setContent(e.target.value) }
Copy the code

ReactCurrentBatchConfig:

A global variable that tracks the configuration of the current batch contains a transition property that starts with a value of 0.

  1. prevTransition = ReactCurrentBatchConfig.transition;
  2. ReactCurrentBatchConfig.transition = 1;
  3. scope();
  4. ReactCurrentBatchConfig.transition = prevTransition;

The transition attribute in ReactCurrentBatchConfig is set to 1 before the Update is performed, the transition attribute is marked as “Transition”, and the transition attribute is set to 0 after the Update

dispatchAction

At this point we start executing the incomingscopeFunction, and that’s wrapped around our update, setState, which is essentially calling dispatchAction.

The important function here, requestUpdateLane, is where the magic begins. This function will give us the priority of the update (remember the urgent and non-urgent updates we talked about earlier), but what is the priority? So this is the React Lane model, and there’s a nice article that you can read about the React Lane model, but I’m just going to talk about it a little bit.

ReactFiberLane

React uses the same concept: 31 tracks are represented by a 31-bit binary, in which the track with a smaller number of digits has a higher priority.

Lanes are Lanes and Lanes are Lanes.

You can seeSyncLaneIs the highest priority, andTransitionLaneThere areArticle 16..TransitionLanesIt contains all of themTransitionLane.

requestUpdateLane

The first thing we can see is that if it’s not concurrentMode it will return directlySyncLane.

requestCurrentTransition

This is going to returnReactCurrentBatchConfigIn thetransitionProperties, remember in this paper, when it introduced startTransition 1 is assigned to each invocation startTransition will ReactCurrentBacthConfig. The transition, so at this time we return value is 1.Back to the requestUpdateLane source code:

isTransition = requestCurrentTransition() ! == NoTransitionCopy the code

NoTransition = 0, requestCurrentTransition = 1, isTransition = true React uses a design where multiple updates labeled “Transition” triggered by the same event are placed on the same Lane with the same priority.

claimNextTransitionLane

This function returns the priority of the update labeled “transition” triggered by the current event.

export function claimNextTransitionLane() :Lane { 
  const lane = nextTransitionLane;  
  / / the initial value for TransitionLane1:0 b0000000000000000000000001000000
  nextTransitionLane <<= 1;  
  /* Move the byte one bit to the left for example: 0 b0000000000000000000000001000000 = > 0 b0000000000000000000000010000000 equals from TransitionLane1 to TransitionLane2 * / 
  if ((nextTransitionLane & TransitionLanes) === 0) { 
  // If you run out of TransitionLanes (16), start from the beginning with priority TransitionLane1
    nextTransitionLane = TransitionLane1; 
  } 
  return lane; 
} 
Copy the code

Review the previous transition Lane model, there are 16 transition lanes. We assign a Lane to each transition update from top to bottom until all 16 transition lanes are used up. For the next update, we will arrange the first Lane (TransitionLane1) from scratch. We can imagine that in a shopping mall, we will start looking for a parking space on the top floor, stop when there is a space, and return to the roof when there is no space on the first floor.

getEventPriority: Determine the priority of other updates

Now that we know that updates wrapped by startTransion() are given a “less urgent” priority TransitionLane, how are other updates prioritized? For example, the input events in our demo.

React prioritises the type of event that triggers the update:

You can see that the input event has the highest precedence, which is why the numbers entered in the Demo are rendered first.

conclusion

Now we have got the priority of TransitionLane for this update, which is called “less urgent priority” in our Demo, and the user input event has got the higher priority of DiscreteEventPriority(SyncLane). React 18 Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler Scheduler

❤️ Thank you

That is all the content of this sharing. I hope it will help you

Don’t forget to share, like and bookmark your favorite things.

Welcome to pay attention to the public number ELab team receiving factory good article ~

We are from the front end department of Bytedance, responsible for the front end development of all bytedance education products.

We focus on product quality improvement, development efficiency, creativity and cutting-edge technology and other aspects of precipitation and dissemination of professional knowledge and cases, to contribute experience value to the industry. Including but not limited to performance monitoring, component library, multi-terminal technology, Serverless, visual construction, audio and video, artificial intelligence, product design and marketing, etc.

Bytedance school/social recruitment internal promotion code: JD345JU

Post links: jobs.toutiao.com/s/RfxWn66