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

React 中hooks之useTransition使用总结

目录

  1. 概述
  2. 基本用法
  3. 使用场景
  4. 最佳实践
  5. 注意事项

概述

什么是 useTransition?

useTransition 是 React 18 引入的新 Hook,用于标记非紧急的状态更新。它允许组件在状态转换期间保持响应,通过将某些更新标记为"过渡"来推迟它们的渲染。

主要特点

  • 保持 UI 响应性
  • 区分紧急和非紧急更新
  • 提供加载状态指示器
  • 不会阻塞用户交互

基本用法

1. 基本语法

import { useTransition } from 'react';function MyComponent() {const [isPending, startTransition] = useTransition();const [count, setCount] = useState(0);const handleClick = () => {startTransition(() => {setCount(c => c + 1);  // 这个更新被标记为过渡,当某次更新造成页面阻塞时,用户点击其他组件操作,此时会降低此次更新的优先级,不阻塞页面渲染先更新优先级高的操作,startTransition中只能写同步的代码,异步代码会打断低优先级,比如不能使用setTimeout});};return (<div>{isPending && <Spinner />}<button onClick={handleClick}>Increment</button><p>Count: {count}</p></div>);
}//isPending为true是表示当前渲染阻塞避免页面出现卡顿现象先显示loading状态组件,直到isPending为false时将展示渲染好的组件

2. 带加载状态的示例

function SearchResults() {const [query, setQuery] = useState('');const [results, setResults] = useState([]);const [isPending, startTransition] = useTransition();const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {// 立即更新输入值(紧急更新)setQuery(e.target.value);// 将搜索结果更新标记为过渡(非紧急更新)startTransition(() => {// 模拟搜索操作const searchResults = performSearch(e.target.value);setResults(searchResults);});};return (<div><input value={query} onChange={handleSearch} />{isPending ? (<div>Loading...</div>) : (<ul>{results.map(result => (<li key={result.id}>{result.title}</li>))}</ul>)}</div>);
}

使用场景

1. 大量数据渲染

function DataGrid() {const [data, setData] = useState([]);const [isPending, startTransition] = useTransition();const [filter, setFilter] = useState('');const handleFilterChange = (newFilter: string) => {setFilter(newFilter);  // 立即更新过滤条件startTransition(() => {// 延迟大量数据的过滤和渲染const filteredData = processLargeDataSet(newFilter);setData(filteredData);});};return (<div><input value={filter} onChange={e => handleFilterChange(e.target.value)} />{isPending ? (<LoadingGrid />) : (<VirtualizedGrid data={data} />)}</div>);
}

2. 路由切换

function App() {const [isPending, startTransition] = useTransition();const [currentPage, setCurrentPage] = useState('home');const navigate = (page: string) => {// 立即更新导航状态startTransition(() => {setCurrentPage(page);});};return (<div><Navigation onNavigate={navigate} />{isPending ? (<PageTransitionSpinner />) : (<Page name={currentPage} />)}</div>);
}

3. 表单验证

function ComplexForm() {const [formData, setFormData] = useState({});const [errors, setErrors] = useState({});const [isPending, startTransition] = useTransition();const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {const { name, value } = e.target;// 立即更新表单值setFormData(prev => ({...prev,[name]: value}));// 将复杂的验证逻辑标记为过渡startTransition(() => {const validationErrors = validateFormField(name, value);setErrors(prev => ({...prev,[name]: validationErrors}));});};return (<form><input name="email" onChange={handleChange} value={formData.email || ''} />{isPending ? (<ValidatingIndicator />) : (errors.email && <ErrorMessage error={errors.email} />)}</form>);
}

最佳实践

  1. 区分更新优先级
function UserProfile() {const [isPending, startTransition] = useTransition();const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {// 高优先级:直接更新输入值setInputValue(e.target.value);// 低优先级:更新预览startTransition(() => {setPreviewData(generatePreview(e.target.value));});};
}
  1. 合理使用 isPending
function LoadingStates() {const [isPending, startTransition] = useTransition();return (<div>{/* 使用骨架屏而不是简单的加载指示器 */}{isPending ? (<Skeleton />) : (<Content />)}</div>);
}

注意事项

  1. 不要在 transition 中包含紧急更新
// ❌ 错误示例
startTransition(() => {setInputValue(e.target.value);  // 这应该是紧急更新
});// ✅ 正确示例
setInputValue(e.target.value);    // 紧急更新
startTransition(() => {setSearchResults(search(e.target.value));  // 非紧急更新
});
  1. 避免不必要的 transition
// ❌ 不需要 transition
startTransition(() => {setCount(count + 1);  // 简单的状态更新不需要 transition
});// ✅ 适合使用 transition
startTransition(() => {setFilteredItems(items.filter(complexFilter));  // 复杂计算
});

总结

  1. useTransition 适用场景:

    • 大量数据处理
    • 复杂 UI 更新
    • 后台计算
    • 非阻塞渲染
  2. 主要优势:

    • 提升用户体验
    • 保持 UI 响应性
    • 优化渲染性能
    • 提供加载状态
  3. 使用建议:

    • 合理区分更新优先级
    • 适当处理加载状态
    • 避免过度使用
    • 配合其他性能优化手段
http://www.lryc.cn/news/524201.html

相关文章:

  • 怎样使用树莓派自己搭建一套ADS-B信号接收系统
  • Chrome谷歌浏览器如何能恢复到之前的旧版本
  • 路由器旁挂三层网络实现SDWAN互联(爱快SD-WAN)
  • 代码随想录算法训练营第五十五天 |108.冗余连接 109.冗余连接Ⅱ
  • Unity补充 -- 协程相关
  • 【第二十周】U-Net:用于生物图像分割的卷积神经网络
  • 部署Metricbeat监测ES
  • Pytorch|YOLO
  • 云计算与物联网技术的融合应用(在工业、农业、家居、医疗、环境、城市等整理较全)
  • 基于python+Django+mysql鲜花水果销售商城网站系统设计与实现
  • Golang:报错no required module provides package github.com/xx的解决方法
  • 数据结构与算法(2):顺序表与链表
  • 华为OD机试E卷 --过滤组合字符串--24年OD统一考试(Java JS Python C C++)
  • QT跨平台应用程序开发框架(3)—— 信号和槽
  • 从 0 开始实现一个 SpringBoot + Vue 项目
  • 【无标题】微调是迁移学习吗?
  • 虚幻基础1:hello world
  • C链表的一些基础知识
  • JDK长期支持版本(LTS)
  • 【超详细】Python datetime(当前日期、时间戳转换、前一天日期等)【附:时区原理详解】
  • 【Excel】【VBA】双列排序:坐标从Y从大到小排列之后相同Y坐标的行再对X从小到大排列
  • 为什么相关性不是因果关系?人工智能中的因果推理探秘
  • Nginx调优
  • 联德胜w801开发板(四)实现腾讯云mqtt的订阅和发布
  • LLM框架对比选择:MaxKB、Dify、FastGPT、RagFlow【RAG+AI工作流+Agent]
  • C语言内存之旅:从静态到动态的跨越
  • 研1如何准备才能找到大厂实习?
  • 游戏为什么失败?回顾某平庸游戏
  • QT 使用QTableView读取数据库数据,表格分页,跳转,导出,过滤功能
  • 【前端】CSS学习笔记(1)