【51CTO.com快译】业界期待已久的React 18版本终于要发布了。据其团队透露,他们的React 18 alpha版本及其相关计划,已经被“安排在路上了”。而根据2019年的一项前端框架调查,React JS已持续被誉为最受欢迎的框架之一。因此,开发人员社区对该框架的期望也在逐年攀升。不过,鉴于React 17的最终版在开发人员社区中,并不太受欢迎。因此,这次React团队尝试添加了各种新的特性与功能,并旨在通过首发计划,来获取用户的及时反馈。
从React 18的准备过程我们可以了解到,他们召集了一个由技术专家、代码库贡献者、培训师、以及开发人员所组成的小组。我从他们在GitHub的讨论组处收集到的信息可知,他们通过周密的计划与开发,希望React 18能够大放异彩。
React 18的新特性主要涉及到:
- 针对一些重要的开箱即用性能的改进
- 新的并发功能
- 服务器端渲染区域的基础性改进
在本文中,我将基于自己对于React 18的解释探索和研究,向您介绍React 18的四个主要新特性。
1. 并发性(Concurrency)
并发性是一种能够同时执行多项任务的能力。在React 18中,它是作为主要新特性出现的。下面,让我们来考虑一个标准的React应用场景。假设有一个带有动画显示效果的组件界面。用户可以输入或单击界面上对应的React组件。
其动态效果为:当用户输入文字和点击按钮时,其对应的动画效果会在React的上下文处予以呈现。在此过程中,React必须处理所有的函数调用、钩子调用、以及事件回调,以保证它们可以同时发生。如果React一直把时间花费在渲染动画帧上,而无法对用户的输入做出反应,那么他们就会认为应用程序卡住了。
由于React工作在单线程的进程中,因此它必须合并,重新排序,以及优先处理某些事件和函数,以便为用户提供最佳、且高质量的使用体验。对此,React在内部使用到了一个“调度程序”,专门负责对此类回调和请求进行优先级的排序。
可以说,在React 18之前,用户并不能控制这些函数的调用顺序。但是React 18则可以通过Transition API(下文将做详细讨论),向用户提供对于这类事件循环的各种控制。
2. 自动批处理(Automatic Batching)
从概念上说,为了提高性能,一组React将多个状态更新放入一次渲染中的操作,被称为批处理。通常,当同一个点击事件中带有两个、或两个以上的状态更新时,那么React会将它们作为一次性的重新渲染(re-render)进行批处理。例如,在如下代码段正在运行时,当您进行一次单击时,尽管您在后台设置为两个状态,但是React也只会执行一次性的代码渲染:
JavaScript
- function App() {
- const [count, setCount] = useState(0);
- const [flag, setFlag] = useState(false);
- function handleClick() {
- setCount(c => c + 1); // Does not re-render yet
- setFlag(f => !f); // Does not re-render yet
- // React will only re-render once at the end (that's batching!)
- }
- return (
- <div>
- <button onClick={handleClick}>Next</button>
- <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
- </div>
- );
- }
由于合理地避开了那些不重要的重新渲染,因此该机制对于性能的维持是十分有利的。同时,它还可以防止组件去渲染那些仅更新了单个状态、却还处于半完成状态的变量,所产生的错误。您可以假想一个场景:在您只选择了第一道菜时,餐厅的服务员是不会跑到后厨下单的,而是会等到您完成了所有菜品的选择后再去。
不过,React的批量更新时间并不固定。其原因在于:过去,React只在浏览器产生事件(如:用户的点击)时,执行批量更新,而此处我们是在事件已经处理之后,才去更新其状态(如:在fetch的回调中)。请参见如下代码段:
JavaScript
- function App() {
- const [count, setCount] = useState(0);
- const [flag, setFlag] = useState(false);
- function handleClick() {
- setCount(c => c + 1); // Does not re-render yet
- setFlag(f => !f); // Does not re-render yet
- // React will only re-render once at the end (that's batching!)
- }
- return (
- <div>
- <button onClick={handleClick}>Next</button>
- <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
- </div>
- );
- }
在React 18引入了自动批处理的方式之后,无论其状态来自何处,它都会一次性地执行重新渲染。当然,如果您并不想采取批量处理的方式,则可以按照如下代码段所示,使用Flash同步,来重新渲染目标组件。
3. 让SSR支持Suspense
在典型的React SSR(服务器端渲染,Server Side Rendering)应用程序中,为了让服务端直接返回HTML文本给浏览器,应用程序通常会发生如下的后台步骤:
- 服务器检索那些必须显示在UI上的相关数据。
- 服务器将整个应用程序渲染为HTML,并将其作为响应传输到客户端。
- 客户端下载JavaScript包(不包括HTML)。
- 最后,客户端将JavaScript逻辑连接到HTML上,也就是我们常说的“水合(hydration)”。
当然,典型的SSR应用程序存在着一个问题,即:整个应用程序的每一步,都必须在较短的时间内迅速完成之后,才能开始下一步。 如今的React 18通过Suspense组件,能够对此类问题进行合理的改进。它会将应用程序分解成为遍历上述步骤的更小的独立单元,以便更快地进行交互,并向用户呈现应用的内容。
4. 转换(Transition)
作为React 18的一项新功能,Transition API能够协助用户解决,在大数据量页面上出现的频繁更新的问题。例如,如果需要在已输入的区域内过滤出数据列表,那么您就必须在对应的状态中,求解该区域的值,以分离出数据,进而控制输入进来的字段值。为此,您可以使用“setSearchQuery(input);”来更新输入值,并搜索结果。
因此,每当有用户键入任何字符时,我们都需要更新输入值,并使用新的值来查找列表,以最终显示结果。而当所有的内容都被渲染到大数据量的页面上时,这可能会导致页面更新的延迟,从而使其他交互或输入变得缓慢、甚至无响应。此外,即使您的列表并不太长,用户在每次击键列表项时,后台的交互也可能变得非常复杂。因此,我们需要找到能够优化渲染的直接方法。
从概念上说,我们通常会碰到两种类型的更新。第一类是紧急更新,您必须更改输入字段的值,以及与之相关的UI。我们可以使用“setInputValue(input); ”来显示输入的内容。而第二类是不那么紧急的更新--显示搜索结果。我们可以使用“setSearchQuery(input); ”来显示内容。
如下代码段所示,由React 18带来的新的Transition API,可以对更新予以标记:
JavaScript
- import { startTransition } from 'react';
- // Urgent: Show what was typed
- setInputValue(input);
- // Mark any state updates inside as transitions
- startTransition(() => {
- // Transition: Show the results
- setSearchQuery(input);
- });
小结
如前所述,由于React 17并不能满足开发者社区的各项需求,因此大家希望作为升级版的React 18能够带来更多新的功能。不过,我们在上面讨论的功能,只是从其测试版中窥见的特性,也许在发布之时,其最终版本仍会有所微调。当然,从目前来看,诸如并发性等新的功能,足以协助开发人员,提高应用程序的速度和效率。因此,总的说来React 18是值得我们期待的。
原文标题:React 18: Things You Need To Know About React JS Latest Version,作者:Gerrard Cooper
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】