Concurrent, as the React team, proposed the UI mode for several years, which has not been implemented in the actual project for such a long time. While the Reconcile core we currently use in React has been refactorized from stack to Fiber for Concurrent mode, react updates are still in synchronous mode instead of concurrent mode. React 17 does not have breaking change or new apis. It is intended to be a transition to concurrent mode. React 18 is expected to be released as a concurrent mode.

Join us and make trouble

What is the concurrent

Concurrent mainly means “interruptible rendering” and is not really concurrent as JS itself is single-threaded. Rendering interrupts, which keeps the application responsive and avoids blocking, and prioritizes rendering so that the work that needs to be done first gets done. Prior to Concurrent mode, updates to react components were performed recursively from the top down without interruption. With Concurrent mode, we can avoid this and allow higher priority interruptions to render, such as animation, user input, etc. When React Concurrent mode was first proposed, there was an online demo comparing the differences between the two modes. In this demo, you can see that the page animation of Concurrent mode is relatively smooth, but the demo is 4 years old. Next, the demo will be reconfigured using the latest React API to experience the changes brought about by applying concurrent mode.

The Sync update mode is stuck

We rendered a serbinski triangle with many nodes, throughrafJs to write a flex animation, and set a timer, every second to update all nodes of the text, the code is as followsIn the actual rendering, the animation is slow because it takes a lot of time to update the text of all nodes at a time. Open the Performance panel to see the specific JS execution.As can be seen, js executes long task for more than 1s each update, during which RAF has no chance to execute at all, and the animation will naturally lag.

Using Concurrent mode

What happens if the concurrent mode is used, which is easy to enable as followsAfter using concurrent mode, the page does not lag much. Open the Performance panel to see js executionAs you can see, JS execution has become a piece-by-piece execution phase, rather than a situation where there is no interruption for more than 1s, we now have interruptible updates. However, because we did not set the update priority, there would be no update of higher priority to preempt rendering in the process of updating all nodes, so the update process would continue immediately in the next task queue after each time slice is updated, and the page would still be stuck. Then, if we set the JS animation of Raf to a higher priority, so that the update of animation takes precedence over the update of node text, will the page look smooth?

Set the update priority

So how do you set priorities, in React Concurrent modeuseTranstitionThis hook allows you to set the expiration date for updates and to delay component updates beyond the expiration date. So let’s set the delay time for the update process of updating all node text, the code is as follows.For the text update, we set an expiration time of 300 milliseconds. You can see that the animation star is much smoother. Open the Performance panel againCan see a lot of purple said computing style of execution, we set each frame of the calculation of raf animation style got in a timely manner, the animation is so smooth, if careful observation, now compared to before mentioned four years ago the demo will still have the obvious card, four years ago the demo are very smooth all the way, Why is that? Because update can be interrupted in the Reconcile phase of React, but not in the commit phase. In order to ensure the consistency of UI updates, commit is the synchronization phase. Therefore, updating texts of all nodes at each synchronization and commit is time-consuming, resulting in lagAs you can see, the COMMIT phase is uninterrupted for many timings.

Summary and Prospect

Concurrent mode does make the react update more possible, but concurrent is not a silver bullet. In this example, the component is actually wrapped in memo. If the memo is not wrapped, then every update animation will update all the text, even though it is the same text. But it would still take a lot of time, and the animation would still lag. UseTransition also returns a value, isPending, that indicates whether the component is being delayed. So the startTransition is an update that immediately updates the component’s isPending status. The second update is a delayed update that renders the component more times. So the use of apis like Memo and shouldComponentUpdate is even more important. In fact, I rarely use this kind of API to prevent re-rendering in my daily development, because it requires a heavy mental burden to ensure that immutable data streams are guaranteed, but since JS does not support it native-writing immutable data streams as long as there is a subtree of a component that is mutable all the previous work is abandoned. So it’s best to useimmerSuch libraries are guaranteed to be immutable, but incur some learning costs. In short, the concurrent model has its benefits and is not necessarily cheap to learn and use, so what to do? You can’t hit someone with that