ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

open-agents 渲染性能实践:用 useTransition 替代手工 loading 状态

open-agents 渲染性能实践:用 useTransition 替代手工 loading 状态 open-agents 渲染性能实践用 useTransition 替代手工 loading 状态【免费下载链接】open-agentsAn open source template for building cloud agents.项目地址: https://gitcode.com/GitHub_Trending/op/open-agents在 open-agents 这类以长会话、流式交互为主的 React 应用中手动开关 loading 标志是最常见也最容易出错的 UI 状态写法之一。本文基于仓库内 rendering-usetransition-loading 规则属于 vercel-react-best-practices 技能的第 6 类 Rendering Performance 规则完整讲解为什么应该用useTransition的内建 pending 状态来取代手工useStateloading 状态并结合 open-agents Web 应用中会话切换的真实代码说明该模式在 Next.js App Router 场景下的落地方式。规则定位它属于 vercel-react-best-practices 的哪个层级open-agents 仓库在 .agents/skills/vercel-react-best-practices/SKILL.md 中维护了一套由 Vercel 工程实践整理而来的 58 条 React/Next.js 性能规则按 8 个优先级分类组织。本规则所在的 Rendering Performance渲染性能类属于 MEDIUM 优先级的第 6 类而规则文件自身的 frontmatter 将影响面标注得更细--- title: Use useTransition Over Manual Loading States impact: LOW impactDescription: reduces re-renders and improves code clarity tags: rendering, transitions, useTransition, loading, state ---即该规则的影响等级为LOW增量改进收益体现在减少重渲染、提升代码清晰度。按照 README 定义的规则文件结构每条规则都遵循frontmatter 元数据 规则说明 错误示例 正确示例 参考资料的统一格式文件名前缀rendering-自动对应到第 6 节规则 ID 由构建脚本在pnpm build时自动生成。问题手工管理 loading 状态的写法文档给出的反例是一个典型的搜索组件用三个useState分别管理query、results和isLoading在异步搜索回调中手工点亮和熄灭加载标志。function SearchResults() { const [query, setQuery] useState() const [results, setResults] useState([]) const [isLoading, setIsLoading] useState(false) const handleSearch async (value: string) { setIsLoading(true) setQuery(value) const data await fetchResults(value) setResults(data) setIsLoading(false) } return ( input onChange{(e) handleSearch(e.target.value)} / {isLoading Spinner /} ResultsList results{results} / / ) }这种写法至少有四个结构性问题状态容易失步。setIsLoading(true/false)依赖开发者自己在每条出口路径上配对调用。一旦fetchResults抛出异常、组件中途卸载、或后续有人往回调里加一条新的returnisLoading很可能卡在true或永远不再复位——spinner 永久转圈是最典型的事故形态。每次状态翻转都触发额外重渲染。setIsLoading(true)与setQuery(value)是分属不同批次的更新加载开始与结束各引入一轮本来可以避免的重渲染而 UI 真正需要的只是一个有更新正在进行的布尔信号。无法中断。用户连续快速输入时旧的搜索还在飞isLoading的开关时序与新请求交错UI 语义变得难以推理。意图表达弱。isLoading只是有个布尔值阅读代码的人无法分辨这个布尔值背后是一次路由跳转、一次数据刷新还是一次表单提交。正解useTransition 的内建 pending 状态规则给出的正确写法用useTransition返回的[isPending, startTransition]取代手工的isLoading把获取并更新结果这一非紧急的更新包进 transitionimport { useTransition, useState } from react function SearchResults() { const [query, setQuery] useState() const [results, setResults] useState([]) const [isPending, startTransition] useTransition() const handleSearch (value: string) { setQuery(value) // Update input immediately startTransition(async () { // Fetch and update results const data await fetchResults(value) setResults(data) }) } return ( input onChange{(e) handleSearch(e.target.value)} / {isPending Spinner /} ResultsList results{results} / / ) }关键行为拆解紧急/非紧急分离setQuery(value)在 transition 之外同步执行输入框的值立即更新用户打字体验不被打断startTransition内的fetchResults setResults被 React 标记为可中断的低优先级更新。isPending 由 React 托管从startTransition调用开始到 transition 内所有状态更新落定为止isPending自动为true结束后回到false组件无需任何手动维护。async transition 的语义传入async回调时回调内await完成之前 transition 一直处于 pending 状态因此 spinner 的显隐完整覆盖了网络请求的整个生命周期而不是只覆盖一次 setState。中断即恢复新的 transition 开始时旧的自动失效isPending反映的始终是当前这批更新是否完成与手工开关在快速连续输入时的错乱时序形成对比。规则列出的四大收益原文档以列表形式给出了选择useTransition的理由逐条展开Automatic pending state自动 pending 状态不再需要手工管理setIsLoading(true/false)从机制上消灭了标志忘记复位这一类 bug。Error resilience错误韧性即便 transition 内部抛出异常pending 状态也会被 React 正确重置spinner 不会卡死。Better responsiveness更好的响应性高优先级更新如输入回显可以立即提交渲染低优先级更新在后台排队UI 在更新期间保持可交互。Interrupt handling中断处理新的 transition 自动接管未完成的旧更新被丢弃天然适配连续输入、连续点击这类高频交互。从源码结构看这四条收益共同指向一个本质loading 状态不是业务状态而是一次更新正在进行这一事实的投影应当由 React 运行时投影出来而不是由开发者手工镜像。open-agents 仓库中的实战印证会话导航的 optimistic transition 组合该规则并非停留在示例层面open-agents 的 Web 应用apps/webNext.js App Router中已有两处与之同构的生产代码模式都是乐观 UI 立即更新紧急 路由导航包进 transition非紧急。会话内切换 Chatapps/web/app/sessions/[sessionId]/session-layout-shell.tsx中const [_isNavigatingChat, startChatNavigationTransition] useTransition(); const switchChat useCallback( (chatId: string) { if (chatId (optimisticActiveChatId ?? routeChatId)) { return; } const href getChatHref(chatId); prefetchedChatHrefsRef.current.add(href); setOptimisticActiveChatId(chatId); // 紧急侧边栏高亮立即切换 startChatNavigationTransition(() { router.push(href, { scroll: false }); // 非紧急路由推后可被中断 }); }, [getChatHref, optimisticActiveChatId, routeChatId, router], );参见 session-layout-shell.tsx。这里的isPending被显式忽略命名_isNavigatingChat只取startChatNavigationTransition说明使用动机不是显示 spinner而是把路由更新降为可中断的 transition用户连续点击不同 chat 时旧的导航更新可以被新点击直接打断而乐观高亮setOptimisticActiveChatId保持同步提交侧边栏永远不会慢半拍。路由就绪后还通过useEffect将乐观值与真实routeChatId对齐并清空。会话列表切换与归档回退apps/web/app/sessions/sessions-route-shell.tsx采用完全一致的结构const [isNavigating, startNavigationTransition] useTransition(); const handleSessionClick useCallback( (targetSession: SessionWithUnread) { if (targetSession.id (optimisticActiveSessionId ?? routeSessionId)) { return; } const href getSessionHref(targetSession); prefetchedSessionHrefsRef.current.add(href); setOptimisticActiveSessionId(targetSession.id); startNavigationTransition(() { router.push(href, { scroll: false }); }); }, [getSessionHref, optimisticActiveSessionId, routeSessionId, router, startNavigationTransition], );参见 sessions-route-shell.tsx。此外归档当前会话后回到会话列表的路由回退同样包在 transition 中handleArchiveSession约 L156-L168进一步印证凡是由用户高频交互触发、且结果可以稍后落定的路由更新open-agents 都统一交给startTransition处理而不是维护isNavigating之类的手工标志。这两处代码同时印证了文档反例的代价若用手工isLoading式写法管理导航连续快速点击时会出现高亮错位、导航排队、标志无法复位等问题而useTransition的中断语义让最后一次点击生效成为默认行为。与 rerender-transitions 规则的配合rendering-usetransition-loading与同技能第 5 类的 rerender-transitions 规则Use startTransition for non-urgent updates互为表里前者解决非紧急更新的进行状态如何表达用isPending而非手工布尔值后者解决哪些更新应该放进 transition非紧急、可中断的更新。两者配合构成 open-agents 前端交互层的一条通用纪律紧急更新同步提交非紧急更新走 transition进行状态由 React 托管。小结用useTransition返回的isPending替代手工isLoading是仓库规则文件 rendering-usetransition-loading.md 的核心主张影响面 LOW 但直接消除一类状态失步 bug 并减少重渲染。写法要点输入回显等紧急更新留在 transition 外fetch setState等非紧急更新包进startTransition(async () {...})spinner 只依赖isPending。在 open-agents 中会话/Chat 导航乐观高亮 startTransition(() router.push(...))是该模式在 Next.js App Router 下的标准落地形态可直接参照apps/web下两个 shell 组件的实现。【免费下载链接】open-agentsAn open source template for building cloud agents.项目地址: https://gitcode.com/GitHub_Trending/op/open-agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表