当前位置: 首页 > ai >正文

React中useDeferredValue与useTransition终极对比。

文章目录

  • 前言
    • 一、核心差异对比
    • 二、代码示例对比
      • 1. `useDeferredValue`:延迟搜索结果更新
      • 2. `useTransition`:延迟路由切换
    • 三、应用场景总结
    • 四、注意事项
    • 五、原理剖析
        • 1. 核心机制对比
        • 2. 关键差异
        • 3. 代码实现原理
  • 总结


前言

在React的并发模式下,useDeferredValueuseTransition是两个强大的Hook,它们通过延迟非紧急的UI更新来提升用户体验,特别是在处理复杂渲染或高开销任务时。本文将对比这两个Hook的核心差异,并通过实际案例展示它们的典型应用场景。


一、核心差异对比

特性useDeferredValueuseTransition
核心作用延迟单个值的更新,标记为低优先级延迟一段逻辑的执行,标记为低优先级
返回值返回延迟后的值(deferredValue返回[isPending, startTransition]数组
触发时机在组件更新时,优先使用旧值渲染,后台再渲染新值通过startTransition包裹的逻辑会被标记为低优先级
适用场景高频更新的输入框、实时搜索、滚动列表等路由切换、复杂计算、非紧急状态更新(如分页加载)
性能影响减少频繁渲染对主线程的阻塞,提升输入流畅性避免关键任务被阻塞,保持UI响应性
与Suspense集成延迟更新不会触发Suspense的fallback,保持旧版本显示延迟逻辑不会触发Suspense的fallback
底层机制基于并发渲染的优先级调度,动态调整延迟基于并发渲染的优先级调度,允许中断低优先级任务

二、代码示例对比

1. useDeferredValue:延迟搜索结果更新

	import { useState, useDeferredValue, useMemo } from 'react';import { Input, List } from 'antd';import mockjs from 'mockjs';interface Item {id: string;name: string;address: string;}export default function SearchPage() {const [inputValue, setInputValue] = useState('');const [list] = useState<Item[]>(() => {return mockjs.mock({'list|10000': [{'id|+1': 1,name: '@natural',address: '@county(true)',},],}).list;});const deferredQuery = useDeferredValue(inputValue);const isStale = deferredQuery !== inputValue;const filteredItems = useMemo(() => {return list.filter(item =>item.name.toString().includes(deferredQuery),);}, [deferredQuery, list]);return (<div><Inputvalue={inputValue}onChange={(e) => setInputValue(e.target.value)}placeholder="输入搜索内容"/><Liststyle={{opacity: isStale ? '0.2' : '1',transition: 'all 1s',}}renderItem={(item) => (<List.Item><List.Item.Metatitle={item.name}description={item.address}/></List.Item>)}dataSource={filteredItems}/></div>);}

关键点

  • 输入框的inputValue会立即更新,但deferredQuery会延迟更新。
  • 列表过滤仅在deferredQuery变化时触发,避免频繁渲染。
  • 当设备性能较好时,延迟几乎无感知;当设备性能较差时,列表会在用户停止输入后更新。

2. useTransition:延迟路由切换

	import { useState, useTransition } from 'react';import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';function PageA() {return <div>Page A Content</div>;} function PageB() {return <div>Page B Content</div>;}function App() {const [currentPage, setCurrentPage] = useState('A');const [isPending, startTransition] = useTransition();const handleNavigation = (page) => {startTransition(() => {setCurrentPage(page);});};return (<Router><div><nav><Link to="/page-a" onClick={() => handleNavigation('A')}>Page A</Link><Link to="/page-b" onClick={() => handleNavigation('B')}>Page B</Link></nav>{isPending && <p>Loading...</p>}<Routes><Route path="/page-a" element={<PageA />} /><Route path="/page-b" element={<PageB />} /></Routes></div></Router>);}export default App;

关键点

  • 路由切换通过startTransition包裹,标记为低优先级任务。
  • isPending状态显示加载提示,避免用户感到卡顿。
  • 高优先级任务(如用户输入)会优先执行,低优先级任务(如路由切换)会被延迟。

三、应用场景总结

场景推荐Hook原因
高频更新的输入框useDeferredValue延迟搜索结果更新,保持输入流畅性,避免频繁渲染。
实时搜索与过滤useDeferredValue延迟更新搜索结果列表,避免频繁渲染导致卡顿,提升用户体验。
复杂数据渲染useDeferredValue延迟渲染大数据量列表或复杂组件树,避免频繁更新导致卡顿。
路由切换useTransition预加载下一页数据时保持当前页响应,避免用户感到卡顿。
复杂计算任务useTransition延迟处理复杂计算任务,优先处理用户交互,提升UI响应性。
非紧急状态更新useTransition延迟更新非紧急状态(如分页加载),避免阻塞关键任务。

四、注意事项

  1. 避免滥用

    • 仅对用户可感知的非紧急更新使用(如搜索建议、后台数据加载)。
    • 避免对即时反馈的操作(如按钮点击、表单提交)使用,否则会延迟必要反馈,破坏用户体验。
  2. 状态管理

    • startTransition中同时更新多个状态时,React可能无法正确批处理。建议将多个状态包裹在一个对象中处理,或使用useReducer管理复杂状态。
  3. 副作用处理

    • 不要在startTransition中执行网络请求、定时器等副作用。副作用应在useEffect或事件处理函数中执行。
  4. 与Suspense集成

    • 若在startTransition中触发了Suspense回退(如懒加载组件),过渡期间会显示fallback UI。可以通过isPending状态自定义加载提示,避免重复加载效果冲突。
  5. 性能优化

    • 精准定位性能瓶颈,优先优化渲染逻辑,再考虑延迟更新。
    • 延迟值尽量为原始类型或稳定对象,避免不必要的后台渲染。

五、原理剖析

1. 核心机制对比
  • useDeferredValue

    • 作用:延迟单个值的更新,将其标记为低优先级。
    • 原理:React 会优先使用旧值渲染,在后台渲染新值。当高优先级任务(如用户输入)完成时,再更新为新值。
    • 底层:基于并发渲染的优先级调度,动态调整延迟。
  • useTransition

    • 作用:延迟一段逻辑的执行,将其标记为低优先级。
    • 原理:通过 startTransition 包裹的逻辑会被标记为低优先级,React 会优先处理高优先级任务(如用户输入),延迟处理低优先级任务。
    • 底层:基于并发渲染的优先级调度,允许中断低优先级任务。
2. 关键差异
  • 触发方式

    • useDeferredValue:延迟单个值的更新,返回延迟后的值。
    • useTransition:通过 startTransition 包裹逻辑,返回 [isPending, startTransition] 数组。
  • 适用场景

    • useDeferredValue:适用于高频更新的输入框、实时搜索、滚动列表等。
    • useTransition:适用于路由切换、复杂计算、非紧急状态更新(如分页加载)。
  • 性能影响

    • useDeferredValue:减少频繁渲染对主线程的阻塞,提升输入流畅性。
    • useTransition:避免关键任务被阻塞,保持 UI 响应性。
3. 代码实现原理
  • useDeferredValue

    • React 在更新时,会首先尝试使用旧值重新渲染,然后在后台尝试使用新值进行另一次渲染。
    • 如果组件未使用 React.memo,优化可能无效,因为子组件会频繁重新渲染。
  • useTransition

    • startTransition 包裹的逻辑会被标记为低优先级,React 会优先处理高优先级任务。
    • isPending 状态表示是否有待处理的低优先级任务。

总结

useDeferredValueuseTransition是React并发模式下优化渲染性能的重要工具。useDeferredValue适用于延迟单个值的更新,而useTransition适用于延迟一段逻辑的执行。通过合理使用这两个Hook,可以显著提升用户体验,特别是在处理高频更新或复杂渲染任务时。然而,开发者必须小心处理并发渲染带来的复杂性,确保应用的稳定性和可预测性。

http://www.xdnf.cn/news/6771.html

相关文章:

  • p024基于Django的网上购物系统的设计与实现
  • LeetCode Hot100刷题——轮转数组
  • Python爬虫之路(14)--playwright浏览器自动化
  • LeetCode 153. 寻找旋转排序数组中的最小值:二分查找法详解及高频疑问解析
  • mysql数据库-中间件MyCat
  • 【LINUX操作系统】生产者消费者模型(下):封装、信号量与环形队列
  • 【赵渝强老师】在PostgreSQL中访问Oracle
  • “即时取模”的快读 → 数论
  • vscode vue 项目 css 颜色调色版有两个
  • 【Closure-Hayd】
  • Linux面试题集合(5)
  • RJ连接器的未来:它还会是网络连接的主流标准吗?
  • Vue.js教学第四章:Vue.js 模板语法之指令应用
  • 反射机制动态解析
  • 融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径
  • MUSE Pi Pro 开发板 Imagination GPU 利用 OpenCL 测试
  • SpringBoot启动流程深入分析
  • JavaScript【5】DOM模型
  • AI赋能把“杂多集合”转化为“理想集合”的数学建模与认知升级
  • Git 版本控制系统入门指南
  • 基于Llama3的开发应用(二):大语言模型的工业部署
  • (C语言)超市管理系统 (正式版)(指针)(数据结构)(清屏操作)(文件读写)(网页版预告)(html)(js)(json)
  • java函数内的变量问题
  • 高频面试题(含笔试高频算法整理)基本总结回顾25
  • 汽车Wafer连接器:工业设备神经网络的隐形革命者
  • git提交库常用词
  • 深度学习---知识蒸馏(Knowledge Distillation, KD)
  • BGP路由策略 基础实验
  • NY321NY322美光闪存芯片NY323NY336
  • 手机打电话时如何将通话对方的声音在手机上识别成文字