likes
comments
collection

如何在React中使用 useTransition()hook函数的教程

作者站长头像
站长
· 阅读数 16

如何使用React useTransition()hook

有些UI更新应该尽可能快地执行(在输入框中打字,从下拉菜单中选择一个值),而其他的UI更新可以有较低的优先级(过滤一个列表)。

直到现在,React还没有提供一个工具来确定UI更新的优先级。

幸运的是,从React 18开始(截至2021年6月的alpha版本),你可以启用并发模式--它允许你将UI更新标记为高优先级或可中断的低优先级。

在这篇文章中,你将学习如何使用useTransition() 钩子将UI更新标记为低优先级,这对大量非紧急更新特别有用。

1.useTransition() 钩子

默认情况下,React中的所有更新都被认为是紧急的。当快速更新被重度更新拖慢时,这可能会产生一个问题。

如何在React中使用 useTransition()hook函数的教程

然而,从React 18和新的并发功能开始,你可以将一些更新标记为可中断的和非紧急的--所谓的过渡期。这对繁重的UI更新特别有用,比如过滤一个大列表。

如何在React中使用 useTransition()hook函数的教程

useTransition() 是让你在React组件内部访问并发模式功能的钩子。

调用const [isPending, startTransition] = useTransitionHook() ,返回一个包含2个项目的数组。

  • isPending: 表示过渡正在等待
  • startTransition(callback): 允许你将callback 里面的任何UI更新标记为过渡。
import { useTransition } from 'react';
function MyComponent() {
  const [isPending, startTransition] = useTransition();
  // ...
  const someEventHandler = (event) => {
    startTransition(() => {
      // Mark updates as transitions
      setValue(event.target.value);
    });
  }
  return <HeavyComponent value={value} />;
}

为了使用useTransition() 钩子,请确保启用并发模式

2.重度UI更新为紧急

让我们考虑一个例子,当所有的更新都是紧急的,它是如何影响用户体验的。

你有一个员工名字的列表,以及一个用户引入查询的输入字段。该组件突出显示员工姓名中的查询匹配。

下面是一个可能的实现:

import { useState } from 'react';
export function FilterList({ names }) {
  const [query, setQuery] = useState('');
  const changeHandler = ({ target: { value } }) => setQuery(value);
  return (
    <div>
      <input onChange={changeHandler} value={query} type="text" />
      {names.map((name, i) => (
        <ListItem key={i} name={name} highlight={query} />
      ))}
    </div>
  );
}
function ListItem({ name, highlight }) {
  const index = name.toLowerCase().indexOf(highlight.toLowerCase());
  if (index === -1) {
    return <div>{name}</div>;
  }
  return (
    <div>
      {name.slice(0, index)}
      <span className="highlight">
        {name.slice(index, index + highlight.length)}
      </span>
      {name.slice(index + highlight.length)}
    </div>
  );
}

<FilterList names={names} /> 接受一个大的姓名数组。在该组件中, 是包含查询字符串的状态变量。输入字段是一个query 受控组件,当用户输入时更新 状态变量。query

打开演示,在输入栏中快速输入一个查询。你会注意到打字滞后,用户界面在明显的时间内感觉没有反应。

为什么会发生这种情况,以及如何解决?

当用户输入时,更新输入字段的值是一项紧急任务,必须快速执行。然而,通过高亮显示匹配信息来更新列表是一项繁重但不紧急的任务。

沉重的非紧急任务拖慢了轻度紧急任务的速度。

useTransition() 钩子可以帮助你区分紧急和非紧急的UI更新。

3.重的UI更新作为过渡

正如已经提到的,你可以使用useTransition() 钩子来让知道React哪些UI更新是紧急的(比如更新输入字段的值),哪些是非紧急的过渡(比如更新名字列表以突出查询)。

让我们对<FilterList> 组件进行必要的调整。

首先,让我们调用[isPending, startTransition] = useTransition() 钩子以获得对startTransition() 函数的访问。其次,让我们创建一个状态变量来保存专门用于过渡的查询状态值。

import { useState, useTransition } from 'react';
export function FilterList({ names }) {
  const [query, setQuery] = useState('');
  const [highlight, setHighlight] = useState('');
  const [isPending, startTransition] = useTransition();
  const changeHandler = ({ target: { value } }) => {
    setQuery(value);
    startTransition(() => setHighlight(value));
  };
  return (
    <div>
      <input onChange={changeHandler} value={query} type="text" />
      {names.map((name, i) => (
        <ListItem key={i} name={name} highlight={highlight} />
      ))}
    </div>
  );
}

使用过渡功能打开演示。如果你在输入框中快速输入一个查询,你会注意到在列表内突出显示查询时有延迟。

React已经将紧急任务(当用户输入时更新输入字段)的渲染与非紧急任务(在列表内突出显示查询)分开。这样的方法提供了更好的用户体验。

4.总结

React中的并发模式可以让你把紧急任务和非紧急任务分开,使UI更新更方便用户使用。