在React 18中开始使用startTransition

1,226 阅读6分钟

React 18的实验性并发模式的一部分是一个新的功能,叫做startTransition ,它可以防止昂贵的UI渲染被立即执行。

为了理解我们为什么需要这个功能,请记住,强迫昂贵的UI渲染立即完成会阻止较轻和较紧急的UI渲染及时渲染。这可能会使那些需要从紧急的UI渲染中获得即时响应的用户感到沮丧。

一个紧急UI渲染的例子是在一个搜索栏中打字。当你打字时,你希望看到你的打字表现出来并立即开始搜索。如果应用程序冻结了,搜索停止了,你就会感到很沮丧。其他昂贵的UI渲染会使整个应用程序陷入困境,包括你的轻型UI渲染,这些渲染应该是快速的(比如在你输入时看到搜索结果)。

在开发你的React应用时,你可以通过debouncing或throttling来避免这个问题。不幸的是,使用debouncing或throttling仍然会导致应用程序变得没有反应。

startTransition 允许你将应用程序中的某些更新标记为非紧急,因此它们被暂停,而更紧急的更新被优先处理。这使你的应用程序感觉更快,并可以减少你的应用程序中渲染非严格必要项目的负担。因此,无论你在渲染什么,你的应用程序仍然在对用户的输入做出响应。

在这篇文章中,我们将学习如何在你的React应用中使用startTransition ,以便延迟非紧急的UI更新,避免阻塞紧急的UI更新。有了这个功能,你可以在短时间内将你缓慢的React应用程序转换成一个响应式的应用程序。

在我们开始之前,请注意React 18在撰写本文时仍处于alpha阶段,所以startTransition还不是稳定版本的一部分。

开始使用React 18

在开始本教程之前,请确保你具备以下条件。

  • 有关React的工作知识
  • 在你的机器上安装了Node.js

让我们先用create-react-app创建一个React项目。

$ npx create-react-app starttransition_demo

上面的命令创建了一个React项目,使用的是React的最新稳定版本,也就是17版。我们需要使用React 18。进入项目目录内部,删除node_modules 目录。

$ cd starttransition_demo/

$ rm -rf node_modules

在Windows上,你必须使用一个不同的命令来删除该目录。删除该目录后,编辑package.json 。找到这些行。

    "react": "^17.0.2",

    "react-dom": "^17.0.2",

然后,将React的版本从17改为alpha。

    "react": "alpha",

    "react-dom": "alpha",

最后,用yarn 安装库。

$ yarn install

为了确保你已经安装了React 18,你可以像这样从node_modules 目录中检查它。

$ grep version node_modules/react/package.json

  "version": "18.0.0-alpha-6ecad79cc-20211006",

在Windows上,你可以直接打开该文件。

运行服务器以确保你可以运行React 18应用程序。

yarn start

在你的浏览器中打开http://localhost:3000。你应该看到熟悉的React项目的默认页面,有一个旋转的React标志。

启用并发模式

默认情况下,我们的React项目并不支持并发模式。我们需要通过以不同的方式渲染根React节点来启用它。

打开src/index.js 。你可以看到,我们用render 静态方法渲染根节点,该方法来自ReactDOM

ReactDOM.render(

  <React.StrictMode>

    <App />

  </React.StrictMode>,

  document.getElementById('root')

);

为了启用并发模式,我们需要先创建根节点,然后使用该实例的render 方法。把上面的行改为下面的行。

const container = document.getElementById('root')

const root = ReactDOM.createRoot(container);

root.render(

  <React.StrictMode>

    <App />

  </React.StrictMode>

);

注意来自ReactDOMcreateRoot 方法。这将创建一个根节点。

设置一个测试环境

首先,让我们创建一个具有轻度UI渲染和重度UI渲染的React应用程序。打开src/App.js 。你可以看到App 函数的定义显示了一个React标志、一个p 标签和一个链接。

用下面的代码替换App 函数。

function App() {

  const [search_text, setSearchText] = useState("");

  const [search_result, setSearchResult] = useState();

  const handleChange = e => {

    setSearchText(e.target.value);

  };

  useEffect(() => {

    if (search_text==="") {

        setSearchResult(null);

    } else {

        const rows = Array.from(Array(5000), (_, index) => {


              return (


                      <div key={index}>


                    <img src={logo} className="App-logo" alt="logo" />


                    <div>{index + 1}. {search_text}</div>


                      </div>


                );

        });

        const list = <div>{rows}</div>;

        setSearchResult(list);

    }

  }, [search_text]);

  return (

    <div className="App">

        <header className="App-header">

            <div className="SearchEngine">

                <div className="SearchInput">

                    <input type="text" value={search_text} onChange={handleChange} />

                </div>

                <div className="SearchResult">

                    {search_result}

                </div>

            </div>

        </header>

    </div>

  );

}

你需要导入useEffectuseState 。把这一行放在文件的顶部。

import {useState, useEffect } from 'react';

在这里,我们正在创建应用程序的用户界面,由两部分组成:搜索输入和搜索结果。

因为输入法有一个回调,当你在输入法上输入文本时,该文本会作为参数传给setSearchText ,以使用useState 钩子更新search_text 的值。然后,搜索结果就显示出来了。对于这个演示,结果是5000行,其中每一行由一个旋转的React标识和相同的搜索查询文本组成。

我们轻快而直接的UI渲染是搜索输入及其文本。当你在搜索输入上键入文本时,文本应该立即出现。然而,显示5000个React标识和搜索文本是一个昂贵的UI渲染。

让我们看一个例子;试着在我们新的React应用程序中快速输入 "我非常喜欢React"。当你输入 "I "时,应用程序立即在搜索输入上渲染 "I "这个文本。然后,它渲染了5000行。这需要很长的时间,这揭示了我们的渲染问题。React应用程序不能立即渲染全部文本。昂贵的UI渲染使轻型UI渲染也变得缓慢。

你可以自己在应用程序上试试,网址是http://localhost:3000。你会看到一个搜索输入。我也设置了一个演示应用程序

Screenshot of sample React app with searchbar that reads "I love React very much"

我们想要的是让昂贵的UI渲染在加载时不要把轻型UI渲染拖到泥里。它们应该被分开,这就是startTransition

使用startTransition

让我们看看当我们导入startTransition ,会发生什么。你的顶行导入应该是这样的。

import {useState, useEffect, startTransition} from 'react';

然后,把昂贵的UI渲染包在这个函数中。将setSearchResult(list) 改为下面的代码。

      startTransition(() => {

          setSearchResult(list);

      });

现在,你可以再次测试这个应用程序。当你在搜索输入中输入东西时,文本会立即被渲染出来。在你停止后(或几秒钟过去后),React应用会渲染搜索结果。

如果你想在等待昂贵的UI渲染完成时,在搜索结果上显示一些东西,怎么办?你可能想显示一个进度条,给用户一个即时的反馈,让他们知道这个应用正在处理他们的请求。

为此,我们可以使用来自useTransition 钩子的isPending 变量。

首先,将文件顶部的导入行改为下面的代码。

import {useState, useEffect, useTransition} from 'react';

useTransition 钩子中提取isPendingstartTransition 。把下面的代码放在App 函数内的第一行。

  const [isPending, startTransition] = useTransition();

接下来,将<div className="SearchResult"> 的内容改为下面的代码。

            {isPending && <div><br /><span>Loading...</span></div>}

            {!isPending && search_result}

现在,当你在搜索输入框上快速输入文字时,会先显示加载指示器。

Screenshot of search bar in React app with Loading indicator

结论

通过startTransition ,你可以通过分离即时UI渲染和非即时UI渲染来使React应用变得流畅和反应性。通过将所有非紧急的UI渲染放在startTransition 方法内,你的应用程序的使用将更加令人满意。

我们还涵盖了使用isPending 变量来表示转换的状态,以备你想给用户提供反馈。

你可以在这里获得startTransition 演示应用程序的完整代码。你也可以尽情地试验该应用程序的演示。希望这些知识在你构建下一个React应用时对你有用。确保应用程序将是顺利的!

The postGetting started withstartTransition in React 18appeared first onLogRocket Blog.