React Concurrent Mode - The Future of Web Apps

栏目: IT技术 · 发布时间: 4年前

内容简介:When it comes to great UX, performance is one of the key factors. While working on large scale applications we often encounter situations where we have to compromise user experience to keep our apps fast. But what if we could find a way to build apps that

In a recent post , we discussed building great user experiences using React Suspense. Continuing on that post, we will have a look at how React’s new experimental Concurrent mode helps us develop responsive and fast apps. 

When it comes to great UX, performance is one of the key factors. While working on large scale applications we often encounter situations where we have to compromise user experience to keep our apps fast. But what if we could find a way to build apps that are highly performant by default with smooth UX and developer-friendly APIs? React Concurrent Mode is the answer to all of these wishes.

Concurrent React is something that has been under development at Facebook for the past 2 years now. React Fiber, a complete rewrite of React, was done with concurrent mode as central motivation. Though all of the other benefits of React Fiber are worth it themselves but enabling Interruptible Rendering and concurrency is the best amongst them.

React Concurrent Mode - A Theory

What is concurrent React?! As React Docs mention:

Concurrent Mode is a set of new features that help React apps stay responsive and gracefully adjust to the user’s device capabilities and network speed.

Diving deep, Concurrent React can work on multiple tasks at a time and can switch between them depending upon the priority. 

The way UI libraries work today is the blocking render approach: when the library has started rendering it cannot go back, no matter how important the next update is. For example, once the browser has started rendering a list of search results, any change in the search input field has to wait until this rendering is finished. 

This is not the case anymore with concurrent mode. React starts rendering updates in memory and high priority tasks such as a change in an input field can interrupt that rendering process. So when there is a change, React will let the browser paint the change and the rendering process will continue once this high priority task is completed. 

Afterward, upon completion of list rendering, React will commit it to DOM and also be displayed on the screen. In short, With Concurrent React, you can render large amounts of work without blocking user inputs and other high priority tasks on the main thread.

Add ButterCMS to your React app in minutes

Concurrent React can partially render a tree without committing the result to the DOM. For example, React starts rendering an update and it encounters a component that hasn’t finished loading. React will wait for loading to be finished without necessarily rendering some fallback component.

One of the best use cases to demonstrate this will be navigation between different pages. Once a user taps on a link and code to display the component,  an appropriate loading state is not available. Here React can wait for a little and keep showing the current screen fully interactive to avoid bad loading state. Once sufficient data or code is available this transition can be completed. Though it can be done via different techniques Concurrent mode makes it more intuitive for developers.

All of this is done by just a few lines of code as React uses heuristics to decide how urgent updates are.

Enabling React Concurrent Mode

As we discussed in our previous post , the developer experience has been at the core of React’s growth. The same goes for Concurrent React, as it is super easy to adopt. Either you’re relying on class components or cruising with hooks, Concurrent React will support both.

Though Concurrent React is used in production at Facebook, for open source users its available in an experimental version of React. To install the experimental version you can use the following command

npm install react@experimental react-dom@experimental

Unlike other features that don’t require any changes in the existing code base, Concurrent mode requires a little change on the root of the React component tree. Here is that small change

import ReactDOM from 'react-dom';

// Current React - Or Blocking Rendering React:
//
// ReactDOM.render(<App />, document.getElementById('root'));
//
// Concurrent Mode - Or Interruptible Rendering React:

ReactDOM.createRoot(
  document.getElementById('root')
).render(<App />);

One important notice here, the lifecycle methods that were marked as UNSAFE_ in previous React releases are truly unsafe with Concurrent Mode. It is highly recommended that you move to new lifecycle methods for a secure transition to Concurrent Mode.

Understanding APIs

In order to fully utilize Concurrent Mode and develop highly responsive interfaces, React gives developers an intuitive API to handle the transition between states and loading states. 

useTransition

As discussed above unlike blocking rendering where all updates are treated with the same priority, Concurrent Mode allows developers to de-prioritize slower updates to keep interfaces interactive. 

The useTransition hook allows developers to schedule work after higher priority work.

Continuing with an example of showing search results under input, updates in the input are of highest priority to keep UI interactable. However, fetching data and rendering lists is of low priority. Wrapping our update in startTransition communicates to React that these updates are of lower priority and can be scheduled after high priority tasks. 

A number of research about handling loading states suggests that gestures like hover and input change should be handled at the highest priority to avoid laggy outlook of the interface. However, a little bit of wait on click and during page transitions is bearable for users. Supporting this research useTransition hook allows developers to wait for a time period before displaying any loading state.

Here is full API of useTransition hook:

const [startTransition, isPending] = useTransition({
  timeoutMs: 2000,
});

startTransition - Method to wrap low priority updates  

isPending - Boolean indicating if there is any pending low priority update, likely used for showing loading state.

timeoutMs - Milliseconds after the update is marked as pending.

useDeferredValue

React Concurrent Mode allows developers to produce the magic of useTransition themselves . With useTransition we get isPending available right away, whereas useDefferedValue gives us the previous value of state that is in transition. API looks like the following:

const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });

deferredValue will have a previous version of the value for at most timeout milliseconds.

Add ButterCMS to your React app in minutes

This is commonly used to keep the interface responsive when you have something that renders immediately based on user input and something that needs to wait for a data fetch.

SuspenseList

SuspenseList is a component that wraps a bunch of child Suspense components and gives you handles for how to show all of the various loading states.

In apps that render a number of suspense components together, SuspenseList provides the ability to handle how these components are revealed to the user. Let's take an example to render a list of Blog posts on our page. List Component of our page will look like the following.

<SuspenseList revealOrder="forwards">
  <Suspense fallback={<Loader />}>
    <BlogPostItem id={1} />
  </Suspense>
  <Suspense fallback={<Loader />}>
    <BlogPostItem id={2} />
  </Suspense>
  <Suspense fallback={<Loader />}>
    <BlogPostItem id={3} />
  </Suspense>
  ...
</SuspenseList>

SuspenseList takes two props:

  • revealOrder: [forwards | backwards | together] It defines the order in which the children Suspense components should be revealed.
    • together : Quite similar to the  Promise.all API, it renders complete list once all items are available
    • forwards/backwards : This will reveal in sequence one after another, top-down or bottom, even if the component after next is ready it will keep it suspended until the next component is revealed.
  • tail: [collapsed | hidden] It determines how suspended items in the list are shown. By default React will display fallback for all items in the list. 
    • collapsed : It will show only the fallback of the next item in the list
    • hidden : It will hide all fallbacks in the list

Conclusion

As we see today, React Concurrent Mode will allow front-end engineers to develop fast, reliable and scalable interfaces easily, paving the way for higher standards in user experience.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

细节决定交互设计的成败

细节决定交互设计的成败

张亮 / 2009-3 / 49.00元

《细节决定交互设计的成败》是一本非常实用的有关软件界面的交互设计和可用性设计方面知识的书籍,通过采用一问一答的形式,你将会有针对性地学习到一些能够很快应用在自己软件开发工作中的细节知识和诀窍。例如,如何减轻用户的等待感,如何预防和减少用户的使用错误等。另外,你会发现阅读《细节决定交互设计的成败》时会非常轻松和愉悦;这是由于《细节决定交互设计的成败》写作上的两个特点:第一,采用较多日常生活中的例子来......一起来看看 《细节决定交互设计的成败》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具