引入并发模式(仅试验)

警告:

这个文章只是一个介绍还没有引入到稳定版本的试验性功能。

不要在线上应用依赖这个试验性的功能。在这个功能成为React框架一部分之前可能会发生重大的改变,并且也不会有任何的警告。

这个文档只是针对一些想早期使用或具有好奇心的人。如果你刚接触React,你不要被这些特性给影响—你现在完全不用去学习他。

这篇文章主要是对并发模式的一些理论的概述。想要看到更具体的使用文档,可以查看下面的几个部分:

  • 用于获取数据的Suspense,描述了在React中获取数据的新机制。

  • 并发的UI模式,展示了一些可以通过并发模式和Suspense来实现的UI模式。

  • 采用并发模式,解释了你可以如何在项目中尝试并发模式。

  • 并发模式API参考文档,记录了这个试验性功能里新的API。

什么是并发模式?

并发模式是一组新特性,有助于React应用程序保持响应性,并根据用户的设备能力和网速进行适当调整。

这些功能仍处于试验阶段,可能会发生变化。它现在还不是稳定的React版本的一部分,但是你可以在试验性的版本中尝试它们。

阻塞和可中断渲染

为了解释并发模式,我们就使用版本控制来作一个比喻。 如果你在一个团队中工作,你可能会使用像Git这样的版本控制系统,并在分支上工作。当一个分支准备就绪时,你可以将你的工作结果合并到master中,以便其他人可以拉取使用。

在版本控制存在之前,开发工作流程就有很大的不同。那没有分支的概念。如果你想编辑一些文件,你必须告诉每个人在你完成工作之前不要碰那些文件。你甚至不能再这个上面和其他人同时工作 。

这说明了UI库(包括React)通常是如何工作的。一旦他们开始渲染一个更新,包括了创建新的DOM节点和在组件中运行代码,他们就不能中断这个工作。这样会被阻塞,我们称这种方法为"阻塞渲染"。

在并发模式下,渲染是不阻塞的。他是可中断的。这加强了用户体验。它还解锁了以前无法实现的新功能。在看到下一章具体的例子之前,这里对新特性做一个高层次的概述。

可中断的渲染

想象一个场景,比如可过滤的产品的列表。你曾是是否在筛选里输入,每次按下一个键的时候感觉不流畅?更新产品列表的一些工作可能是不可避免的,比如创建新的DOM节点或浏览器进行布局(layout)。但是,我们何时以及如何执行该工作起着很大的作用。

一个常见的解决办法是在输入框输入的时候进行"防抖"。当使用防抖时,我们只会在用户停止键入更新。或者,我们可以对输入进行"节流",并以某个最大频率更新列表。但是在一些低效的设备上,仍然可能会有些卡顿。无论是节流还是防抖都会产生差强人意的用户体验。

卡顿的原因很简单:一旦开始渲染,他就不会被中断。因此浏览器在按键之后无法立即更新文本输入。无论UI库(例如React)在基准(benchmark)上看起来有多好,如果它使用阻塞渲染,则组件中的某些工作总是会造成停顿。而且,通常没有简单的办法去解决。

并发模式通过使渲染可中断来解决此根本限制。 这意味着当用户按下另一个键时,React不需要阻止浏览器更新文本输入。相反,它可以让浏览器为输入绘制一个更新,然后在内存中继续渲染更新后的列表。当渲染完成后,React更新DOM,更改会映射在屏幕上。

从概念上讲,你可以将其视为React在"分支"上准备每个更新。就像你可以放弃分支中的工作或在分支之间进行切换一样,在并发模式下的React可以中断正在进行的更新,以执行更重要的任务,然后返回到之前执行的任务。这种技术可能还会让你想起电子游戏中的双重缓冲

并发模式技术减少了UI中防抖和节流的需求。由于渲染是可中断的,因此React无需人为的去 延迟 工作来避免卡顿。他可以以正确的方式开始渲染,但是当应用需要保持响应的时候,会中断这个工作。

刻意的加载Sequences

我们之前已经说过,并发模式就像React在“分支”上工作一样。分支概念不仅对短期补救有效,对长期的功能也一样。比如你有时候处理某个新功能,可能需要几周才能做到完善并合并到master。版本控制的隐喻的这一方面也适用于渲染。

想象一下,我们正在一个应用程序的两个屏幕之间切换浏览。有时,我们可能没有加载足够的代码和数据来在新屏幕上向用户显示足够好的加载状态。切换到空白屏幕或loading效果可能是一种不和谐的体验。但是,通常所需的代码和数据并不需要很长时间来获取。如果React能在旧屏幕上多停留一段时间,并在显示新屏幕前跳过糟糕的加载状态,那不是更好吗?

虽然这在今天是可能的,但很难协调。在并发模式下,这功能被内置了。React首先开始在内存中准备新屏幕,或者,正如我们的隐喻所说,“在另一个分支上”。因此React可以在更新DOM之前等待,以便可以加载更多内容。当新屏幕准备就绪时,React可以带我们进入它。

并发

让我们回顾一下上面的两个例子,看看并发模式如何将它们统一起来。在并发模式下,React可以 同时 处理多个状态更新 —— 就像分支让不同的团队成员独立工作一样。

  • 对于关联到CPU的更新(比如创建DOM节点和运行组件代码),并发意味着更紧急的更新可以“中断”已开始的渲染。

    笔: 标记,更紧急意味着哪些?

  • 对于关联到IO的更新(比如从网络获取代码或数据),并发意味着React可以在所有数据到达之前在内存中开始渲染,并跳过空加载状态。

重要的是,使用 React的方式是相同的。组件,props和state之类的概念从根本上以相同的方式工作。当你想更新屏幕时,你就设置状态。

React使用启发式的方法去决定更新的紧急程度,而且也可以让你用几行代码来对这个进行调整,这样你就可以在每次交互的时候去提升用户所需的体验。

把探索投入到生产

围绕着并发模式特性有一个共同的主题。他的任务就是将人机交互的探索投入到真实UI中。

例如,研究表明,在屏幕之间切换时显示过多的中间加载状态会使切换的速度感觉变慢。这就是为什么并发模式在固定的“调度”上显示新的加载状态,以免造成震动和过于频繁的更新。

同样,从研究中我们知道,悬停和文本输入之类的交互需要在很短的时间内处理,而单击和页面转换可以等待更长的时间而不会感到迟钝。并发模式在内部使用的不同“优先级”大致对应于人类感知研究中的交互类别。

专注于用户体验的团队有时会使用一次性解决方案来解决类似的问题。然而,这些解决方案很少能长期存在,因为它们很难维护。使用并发模式,我们的目标是将UI研究结果转化为抽象本身,并提供使用它们的惯用方法。作为一个UI库,React可以很好地做到这一点。

接下来的内容

现在知道了并发模式是什么了。

下面的内容,会有更具体的介绍:

笔者总结

总的来说,并发模式是两周:

  • cpu(DOM节点的更新和代码运行)

  • IO(获取数据和代码等)

对于更新优先级,react根据调研有套人类感知的大致方案,但是也运行开发者手动协调。可以从后续的内容来验证。

Last updated