startTransition:React 18 的并发渲染控制详解

367 阅读2分钟

startTransition 是 React 18 引入的核心 API 之一,可以让你在后台渲染 UI 的一部分。用于标记某些状态更新为非紧急优先级,允许 React 在不阻塞 UI 渲染的情况下处理这些更新。这一特性显著提升了复杂应用的响应性和用户体验。

核心概念与原理

在 React 18 中,渲染分为两种优先级:

  • 紧急更新(Urgent Updates):如点击、输入等直接交互,需要立即响应。
  • 过渡更新(Transition Updates):如页面导航、数据加载等不需要立即完成的更新。

startTransition 的作用是将紧急更新转变为过渡更新,允许 React 在用户交互期间继续保持界面响应,而不是被耗时的渲染任务阻塞。

基本用法

你可以通过将一个 state 包裹在 startTransition 回调中,将其更新标记为一个 transition

这里以搜索框优化为例:

import { useState, startTransition } from 'react';

function SearchComponent() {
  const [inputValue, setInputValue] = useState('');
  const [searchResults, setSearchResults] = useState([]);

  const handleInputChange = (e) => {
    const value = e.target.value;
    // 紧急更新:立即更新输入框值
    setInputValue(value);

    // 过渡更新:延迟更新搜索结果
    startTransition(() => {
      setSearchResults(fetchResults(value));
    });
  };

  return (
    <div>
      <input value={inputValue} onChange={handleInputChange} />
      <SearchResults results={searchResults} />
    </div>
  );
}

注意事项:

  • 传递给 startTransition 的函数会被立即执行,并将在其执行期间发生的所有状态更新标记为 transition。如果你尝试在 setTimeout 中执行状态更新,它们将不会被标记为 transition。
  • 只有在可以访问该状态的 set 函数时,才能将其对应的状态更新包装为 transition。如果你想启用 Transition 以响应某个 prop 或自定义 Hook 值,请尝试使用 useDeferredValue
  • 标记为 Transition 的状态更新将被其他状态更新打断。例如在 Transition 中更新图表组件,并在图表组件仍在重新渲染时继续在输入框中输入,React 将首先处理输入框的更新,之后再重新启动对图表组件的渲染工作。
  • Transition 更新不能用于控制文本输入。

使用场景

  1. 复杂渲染更新:如长列表、图表等需要大量计算的渲染。
  2. 导航与路由切换:页面切换时保持界面响应。
  3. 数据获取与加载:在等待数据时允许用户继续交互。
  4. 状态批量更新:合并多个状态更新,减少渲染次数。

useTransition 与 startTransition 的区别

特性useTransitionstartTransition
类型React Hook独立函数
返回值[isPending, startTransition]无返回值
Pending 状态提供 isPending 状态指示器不提供状态指示器
使用场景组件内部组件外部或事件处理函数中
依赖关系需要 React 18+ 和并发模式需要 React 18+
典型用例UI 加载状态指示库/工具函数中的状态更新

通过合理使用 startTransition,可以让你的 React 应用在处理复杂渲染时保持流畅的用户体验,达到接近原生应用的响应速度。