React 并发功能体验(前端的并发模式)

React 是一个开源 JavaScript 库,开发人员使用它来创建基于 Web 和移动的应用程序,并且支持构建交互式用户界面和 UI 组件。React 是由 Facebook 软件工程师 Jordan Walke 创建,React 的第一个版本在七年前问世,现在,Facebook 负责维护。React框架自首次发布以来,React 的受欢迎程度直线飙升,热度不减。
2020 年 10 月,React 17 发布了,但令人惊讶的是——“零新功能”。当然,这并不是真的表示没有任何新添加的功能,让广大程序员使用者兴奋。事实上,这个版本为我们带来了很多重大功能的升级及16版本的bug修复,并推出了:Concurrent Mode 和Suspense。
虽然这两个功能尚未正式发布,这些功能已提供给开发人员进行测试。一旦发布,它们将改变 React 呈现其 UI 的方式,从而达到双倍提高性能和用户体验。

简要说明, Concurrent Mode 和Suspense 可以使用户无缝处理数据加载,加载状态,用户界面操作更加平滑和无缝切换。 在Concurrent Mode 下,React可以暂停高消耗的,非紧急的组件的渲染,并聚焦在更加紧迫的任务处理,如UI 渲染,始终保持应用为可响应式,避免白屏,卡顿等现象。

本文主要分享深入了解Concurrent Mode 和Suspense 模式下的数据提取功能。

为什么需要 Concurrent Mode?

众所周知,JavaScript 框架或库是单线程的工作。因此,当一个代码块运行时,其余的块必须等待执行。无法并发执行多线程工作。界面渲染也是一样的。
一旦 React 开始渲染某些东西,无法中断直到运行完成。React 开发人员将这种渲染称为“阻塞渲染”。 这种阻塞渲染会创建一个不稳定的用户界面,并且随时可能停止响应。

具体问题

假如,我们需要显示一个很长的可选列表用于过滤产品的应用程序。我们使用搜索框用于过滤记录,设计方案是当用户点击搜索按钮后,用户界面需要重新刷新列出相关联的数据。

如果列表过长,数据过多,UI“卡顿”,即渲染对用户可见。这种卡顿也会大大降低产品性能。开发人员可以使用一些技术,如节流和防抖,这些技术会有一定帮助,但不是完美的解决方案。
节流限制特定函数被调用的次数。使用节流,我们可以避免重复调用昂贵和耗时的API或函数。这个过程能够提高性能,尤其是在用户界面上呈现信息。

防抖会在预定的时间内忽略对函数的调用。函数调用仅在经过预定时间后进行。

下图描述了卡顿现象:
在等待非紧急 API 调用完成时,UI 卡顿,从而阻止呈现用户界面。解决方案是使用并发模式进行可中断渲染。

无中断渲染

通过可中断渲染,React.js 在处理和重新渲染列表时不会阻塞 UI。它通过暂停琐碎的工作、更新 DOM 并确保 UI 不会卡顿,使 React.js 更加细化。React 使用用户输入并行更新或重绘输入框。React 使用用户输入并重绘输入框并行执行。它还更新内存中的列表。React 完成更新后,它会更新 DOM 并在用户的显示器上重新呈现列表。本质上,无中断渲染使 React 能够“多任务”。此功能提供了更流畅的 UI 体验。

并发模式

并发模式是一组功能,可帮助 React 应用程序保持响应并平滑地适应用户的设备和网络速度能力。并发模式将其拥有的任务划分为更小的块。 React 的调度程序可以挑选并选择要执行的作业。作业的调度取决于它们的优先级。通过对任务进行优先级排序,它可以停止琐碎或不紧急的事情,或者进一步推动它们。 React 始终将用户界面更新和渲染放在首位。

使用并发模式,我们可以:

  • 控制首次渲染过程
  • 优先处理渲染过程
  • 暂停和恢复组件的渲染
  • 缓存和优化组件的运行时渲染
  • 隐藏显示内容直到需要展示时

随着 UI 渲染,并发模式改进了对传入数据的响应,懒加载控件,异步处理过程。并发模式保证了用户界面始终处于激活状态,并且持续在后台更新数据,并发模式也始终使用React 的两个钩挂:useTransitionuseDeferredValue

使用useDeferredValue Hook

useDeferredValue Hook 的定义如下:

const deferredValue = useDeferredValue(value, { timeoutMs: <some value> });

此命令设置值在timeoutMs中设置的时间后“滞后”。 用户界面是必须立即更新还是必须等待数据,该命令使用户界面保持激活状态和响应性,该Hook避免了 UI 卡顿,并始终保持用户界面响应,以保持获取数据滞后的较小成本。

使用 Transition Hook

useTransition Hook React 中主要用于挂起的Hook,假设这样的场景下:其中有一个带有用户名按钮的网页。只需点击一个按钮,网页就会在屏幕上显示用户的详细信息。
假设用户首先单击一个按钮,然后单击下一个。屏幕要么变成空白,要么我们在屏幕上看到一个微调器。如果获取详细信息花费的时间太长,用户界面可能会冻结。
useTransition 方法返回两个Hook的值:startTransition isPending。定义的语法如下:

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

startTransition 定义的语法:

<button disabled={isPending}
  startTransition(() => {
        <fetch Calls>
  });
  </button>
  {isPending? " Loading...": null}  

使用 useTransition 钩子,React.js 继续显示没有用户详细信息的用户界面,直到用户详细信息准备好,但 UI 是响应式的。React 优先考虑用户界面,以在并行获取数据时保持响应。

为获取数据的Suspense

SuspenseReact与并发模式一起引入的另一个实验性功能。Suspense使组件能够在渲染前等待一段预定的时间。
Suspense的主要作用是从组件异步读取数据,而无需担心数据的来源。Suspense最适合延迟加载的概念。Suspense允许数据获取库通知React数据组件是否可以使用。在必要的组件准备就绪之前,React不会更新 UI。

使用Suspense的好处:

1.数据获取库和React组件之间的集成

2.控制视觉加载状态

3.避免竞争条件

Spinner组件的基本语法如下:

import Spinner from './Spinner';
    <Suspense fallback={<Spinner />}>
      <SomeComponent />
</Suspense>

Concurrent Mode中使用的Suspense允许耗时的组件在等待数据的同时开始渲染。同时显示占位符。这种组合产生了更流畅的UI体验。

Suspense 和 懒加载组件

React.lazy是一个新功能,它使React.js能够延迟加载组件。懒加载意味着仅在需要时才加载组件(检索和呈现它们的代码)。他们会优先考虑最关键的用户界面组件。React开发人员建议将懒加载组件包装在Suspense组件中。
这样做可确保组件在渲染时不会出现“不良状态”。用户界面在整个过程中保持响应,并带来更流畅的用户体验。

启用并发模式

要启用并发模式,请安装最新的测试版本。安装 React 的先决条件是节点数据包管理器 (npm)。要安装测试版本,请执行以下命令:

npm install react@experimental react-dom@experimental

要测试是否设置了测试版本,请创建一个示例 React 应用程序。没有测试功能的渲染代码如下:

import * as React from 'react';
  import { render } from 'react-dom';
  render(<App />, document.getElementById('root'));  

并发模式的,具体代码如下:

import * as React from 'react';
    import { createRoot } from 'react-dom';
createRoot(document.getElementById('root')).render(<App />);

这将为整个应用程序启用并发模式。React 将渲染调用分为两部分:

  1. 创建根元素
  2. 使用渲染调用

目前,React 计划维护三种模式:

  1. 传统模式是向后兼容的传统或当前模式
  2. 阻塞模式是并发模式开发的中间阶段
  3. 并发模式

阻塞模式是使用createBlockingRoot 调用来替换createRoot 调用,在并发模式的开发情况下,阻塞模式为开发者提供了机会来修复bug或解决问题。

React 官方文档中也说明了每种模式支持的功能:

示例应用:

本文也创建了一个测试程序来验证并发模式和其他模式的用法和效果。本文以像素应用为例在150*150的画布上随机分布像素并包含一个搜索框,每次用户点击搜索框时候,画布会重新渲染自己。
即使UI 界面无法在并发模式下渲染,用户输入也不会停止更新。像素画布在处理完成后重新渲染。在传统模式下,快速键入时,UI 会停止,有时会在再次渲染画布之前停止。用户输入也会停止并且不会更新。

构建像素应用程序的主要文件是 canvas.js。我们还制作了一个输入框,用户可以在其中输入任何内容。每次按下一个键都会重新渲染像素画布。

代码示例:Index.js

import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App";
    // Traditional or non-Concurrent Mode react
    const rootTraditional = document.getElementById("root");
    ReactDOM.render(<App caption="Traditional or Block Rendering" />,
    rootTraditional);
    // Concurrent Mode enabled
    const rootConcurrent = document.getElementById("root-concurrent");
    ReactDOM.createRoot(rootConcurrent).render(<App caption="Interruptible
Rendering"   />);

App.js

import React, { useState, useDeferredValue } from "react";
  import "./App.css";
  import { Canvas } from "./Canvas";
  export default function App(props)
  { const [value, setValue] = useState("");  

 //This is available only in the Concurrent mode.

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

    const keyPressHandler = e => {
      setValue(e.target.value);
    };  

    return (
      <div className="App">
        <h1>{props.caption}</h1>
        <input onKeyUp={keyPressHandler} />
        <Canvas value={deferredValue} />
      </div>
    );
  }

Canvas.js

import React from "react";
   const CANVAS_SIZE = 70;
   const generateRandomColor = () => {
    var letters = "0123456789ABCDEF";
    var color = "#";
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
  };
   const createCanvas = (rows, columns) => {
    let array = [];
    for (let i = 0; i < rows; i++) {
      let row = [];
      for (let j = 0; j < columns; j++) {
        row.push(0);
      }
      array.push(row);
    }
    return array;
  };
   //This is the square with the pixels
  const drawCanvas = value => {
    const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
    return canvas.map((row, rowIndex) => {
      let cellsArrJSX = row.map((cell, cellIndex) => {
        let key = rowIndex + "-" + cellIndex;
        return (
         <div
            style={{ backgroundColor: generateRandomColor() }}
            className="cell"
            key={"cell-" + key}
          />
        );
      });
      return (
        <div key={"row-" + rowIndex} className="canvas-row">
          {cellsArrJSX}
        </div>
      );
    });
  };
  export const Canvas = ({ value }) => {
    return (
     <div>
        <h2 style={{ minHeight: 30 }}>{value}</h2>
       <div className="canvas">{drawCanvas(value)}</div>
     </div>
   );
 };

Index.html

<!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, shrink-to-fit=no"
      />
      <meta name="theme-color" content="#000000" />
      <title>React App Concurrent Mode</title>
    </head>
    <body>
      <noscript>
     You need to enable JavaScript to run this app.
      </noscript>
      <div id="container">
        <div id="root" class="column"></div>
        <div id="root-concurrent" class="column"></div>
      </div>
    </body>
  </html>

运行示例

让我们看看我们的代码。我们看到的第一个屏幕是初始屏幕。使用传统或块渲染是现在React 的做法。可中断渲染是并发模式的测试功能。我们先看看传统的渲染工作。

像素画布在每次击键时重新渲染。在传统渲染中,整个 UI 会在每次击键时暂停,直到它可以重新渲染屏幕。在此期间,即使我们继续打字,用户输入不会更新。

下图显示可中断渲染。在可中断渲染中,用户可以继续输入。在为每次击键并行重新渲染画布时,UI 不会停止或停止。

重新渲染完成后,React 会更新 UI。虽然在静态截图中很难看到,但我们可以看到网格在变化,但用户仍然可以打字而不会出现 UI 卡顿的情况。

总结

在本文中,我们研究了 React 的测试并发功能和 Suspense。使用并发模式,React.js 始终保持用户界面响应。它将应用程序的任务分解为更小的块,并允许对用户界面任务进行优先级排序。因此,此模式可提供更流畅和无缝的用户体验,并提高应用程序的整体性能。

结合并发模式,Suspense 允许用户界面保持响应。同时,数据获取等繁重耗时的任务可以并行完成,从而提供整体无缝体验。

有关并发模式的完整详细信息可在 React 官方文档中了解。
随着React版本的改进, React框架越来越被更多的中国前端开发者所熟知并且广泛应用到他们的项目开发中。是继续Vue.js 后又一备受欢迎的前端主流框架,现在也因此衍生除了很多支持与React框架集成的功能工具, 如前端报表ActiveReportsJS控件,提供了与 React 直接集成的在线编辑器和报表展示工具,完善前端的数据展示功能。

到此这篇关于React 并发功能体验-前端的并发模式已经到来的文章就介绍到这了,更多相关React 并发功能内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React 并发功能体验(前端的并发模式)

    React 是一个开源 JavaScript 库,开发人员使用它来创建基于 Web 和移动的应用程序,并且支持构建交互式用户界面和 UI 组件.React 是由 Facebook 软件工程师 Jordan Walke 创建,React 的第一个版本在七年前问世,现在,Facebook 负责维护.React框架自首次发布以来,React 的受欢迎程度直线飙升,热度不减. 2020 年 10 月,React 17 发布了,但令人惊讶的是--"零新功能".当然,这并不是真的表示没有任何新添加

  • 详解React Angular Vue三大前端技术

    一.[React] React(也被称为React.js或ReactJS)是一个用于构建用户界面的JavaScript库.它由Facebook和一个由个人开发者和公司组成的社区来维护. React可以作为开发单页或移动应用的基础.然而,React只关注向DOM渲染数据,因此创建React应用通常需要使用额外的库来进行状态管理和路由,Redux和React Router分别是这类库的例子. 基本用法 下面是一个简单的React在HTML中使用JSX和JavaScript的例子. Greeter函数

  • Vue.js React与Angular流行前端框架优势对比

    目录 Vue.js.React和Angular对比 以下是Vue.js的代码示例: 以下是React的代码示例: 以下是Angular的代码示例: Vue.js.React和Angular对比 Vue.js.React和Angular都是流行的前端框架,它们都有自己的优势和劣势. 以下是它们的比较: Vue.js Vue.js是一个轻量级的前端框架,它的核心库只有18KB,因此整个框架的体积很小.Vue.js通过简单的API和组件化的架构,使得开发更加简单,易于上手和维护.Vue.js支持双向数

  • 微信小程序 支付功能(前端)的实现

    微信小程序 支付功能(前端)的实现 只提供微信小程序端代码: var app = getApp(); Page({ data: {}, onLoad: function (options) { // 页面初始化 options为页面跳转所带来的参数 var that = this //登陆获取code wx.login({ success: function (res) { console.log(res.code) //获取openid that.getOpenId(res.code) } }

  • React BootStrap用户体验框架快速上手

    官方文档http://react-bootstrap.github.io/getting-started.html 安装 在终端cd到你的项目目录下执行:$ npm install react-bootstrap 然后需要我们手动引用css <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstr

  • react使用CSS实现react动画功能示例

    本文实例讲述了react使用CSS实现react动画功能.分享给大家供大家参考,具体如下: react动画: import React, { Component } from 'react'; class Boss extends Component { constructor(props) { super(props); this.state = { isShow:true } this.toTogger=this.toTogger.bind(this) } render() { return

  • React倒计时功能实现代码——解耦通用

    需求分析 需求 在某个页面中需要有一个倒计时的功能,倒计时 5 s,5s钟后跳转到新的界面 分析 首先是实现倒计时功能 其次是实现在每倒计时 1 s后页面上要执行 倒计时秒数变化的功能 最后是实现倒计时完成后 跳转到指定页面的功能 初版做法 代码 let waitTime = 5 class DemoPage extends React.Component { constructor(props) { super(props); this.state = { time: '', }; } com

  • Java 高并发十: JDK8对并发的新支持详解

    1. LongAdder 和AtomicLong类似的使用方式,但是性能比AtomicLong更好. LongAdder与AtomicLong都是使用了原子操作来提高性能.但是LongAdder在AtomicLong的基础上进行了热点分离,热点分离类似于有锁操作中的减小锁粒度,将一个锁分离成若干个锁来提高性能.在无锁中,也可以用类似的方式来增加CAS的成功率,从而提高性能. LongAdder原理图: AtomicLong的实现方式是内部有个value 变量,当多线程并发自增,自减时,均通过CA

  • IntelliJ IDEA 2022.2 正式发布新功能体验

    目录 01主要更新 02用户体验 03编辑器 04Java 05Kotlin 06Groovy 07安全性 08Docker 09QA 工具 10Scala 11其他 IntelliJ IDEA 2022.2为远程开发功能带来了多项质量改进,使其更美观.更稳定.从 v2022.2 开始,IntelliJ IDEA 使用 JetBrains Runtime 17,后者可以从多方面增强 IDE 体验和性能.IntelliJ IDEA Ultimate 添加了对 Spring 6 和 Spring B

  • 微信小程序开发搜索功能实现(前端+后端+数据库)

    2019年5月7日更新这是写的最新的一篇文章大家看这篇:https://www.jb51.net/article/157081.htm 界面比较丑,主要实现逻辑... 超级简单的界面,表单,提交按钮,搜索结果展示区域... 下面是index.wxml <!--index.wxml--> <form bindsubmit="formSubmit"> <!--提交按钮 --> <input type="text" name=&q

随机推荐