欢迎光临
我们一直在努力

useTransition:如何让 React 更新“让路”

目录

为什么需要useTransition

React 中的两类更新

紧急更新

非紧急更新

如何使用useTransition

isPending常见用法

实战案例

规则

总结


本篇我们将学习 useTransition 是用来解决什么问题的,以及它与 React 并发架构(Fiber)之间的关系。

在理解 useTransition 之前,我们需要一个重要的前置知识:React Fiber。

从 React 16 开始,React 引入了 Fiber 架构,其核心目的在于:

让渲染过程可以被拆分、打断和恢复。

在 Fiber 之前,React 的更新是一次同步递归过程,一旦开始执行,无法被中断;

而在 Fiber 架构下,React 可以根据任务的优先级,暂停当前工作,先去处理更重要的更新。

而 useTransition,能够让开发者控制“优先级调度能力”。

也就是告诉 React:这个更新不着急,可以被打断,让更重要的更新先执行。

它并不是用来“延迟更新”,也不是节流、防抖,而是改变一次更新在调度系统中的优先级。

如果不清楚Fiber是什么可以参考以下文章

从 JSX 到 Fiber:完整拆解一次 React 渲染流程-CSDN博客

为什么需要useTransition

考虑一个常见的场景:

页面中渲染了一个包含 100 条数据的列表, 这个时候列表更新本身会触发大量组件重新 render,此时用户点击了一个按钮,希望立即得到反馈

在没有并发能力的情况下:

列表渲染任务会占用主线程,按钮点击产生的更新被阻塞,用户将感知到明显卡顿

而当我们使用 useTransition 包裹列表更新时:

列表渲染会被标记为低优先级任务用户点击按钮产生的更新会被优先执行,列表渲染可以被暂停,稍后继续

这就是 useTransition 解决的核心问题

React 中的两类更新

紧急更新

那么,我们紧急任务就比如有

  • 输入框输入
  • 点击、hover
  • 滚动

这些是关于用户的点击动作,一般我们都作为高优先级

非紧急更新

  • 根据输入过滤列表
  • 切换 Tab
  • 页面内容刷新

这些任务就可以稍微慢一些,可以被中断

useTransition 就是用来 标记「非紧急更新」的。

如何使用useTransition

isPending表示的是是否还有没完成的transition更新

startTransition 中表示的是我们需要标记transition的任务,也就是设置低优先级的任务。

const [isPending, startTransition] = useTransition()

function onChange(e) {
const value = e.target.value
setInput(value) // 紧急更新
startTransition(() => {
setList(filter(value)) // 非紧急更新
})// 在这里,React 会将这次 setList 更新标记为 transition 更新,并交由 Scheduler 以较低优先级调度执行。
}

isPending常见用法

就比如我们在列表渲染的时候需要显示loading,这个时候我们就可以使用isPneding。

{isPending && <Loading />}

实战案例

1️⃣ 搜索 / 列表过滤

输入框输入,根据输入过滤 大列表,每次输入可能都会触发大量渲染,输入框出现卡顿

function SearchList({ list }) {
const [keyword, setKeyword] = useState('')
const [filtered, setFiltered] = useState(list)
const [isPending, startTransition] = useTransition()

function onChange(e) {
const value = e.target.value
setKeyword(value) // 紧急更新

startTransition(() => {
setFiltered(
list.filter(item => item.includes(value))
)
})
}

return (
<>
<input value={keyword} onChange={onChange} />
{isPending && <span>Filtering…</span>}
<List data={filtered} />
</>
)
}

2️⃣ Tab 切换(内容区域很重)

点击 Tab,切换的是复杂页面(表格 / 图表)

function Tabs() {
const [tab, setTab] = useState('A')
const [isPending, startTransition] = useTransition()

function switchTab(next) {
startTransition(() => {
setTab(next)
})
}

return (
<>
<button onClick={() => switchTab('A')}>A</button>
<button onClick={() => switchTab('B')}>B</button>

{isPending && <Loading />}
<TabContent tab={tab} />
</>
)
}

规则

react官方说了一些,就是我们传递给 startTransition 的函数被称为 “Actions” 

按照约定,任何在 startTransition 内调用的回调函数(例如作为回调的 prop)应命名为 Action 或包含 “Action” 后缀:

function SubmitButton({ submitAction }) {
const [isPending, startTransition] = useTransition();

return (
<button
disabled={isPending}
onClick={() => {
startTransition(async () => {
await submitAction(); //比如这个提交函数,最后面就用action结尾
});
}}
>
Submit
</button>
);
}

总结

  • useTransition 不是延迟更新,而是降低更新优先级
  • 它用于提升复杂 UI 场景下的用户交互体验
  • 本质是 React 并发架构(Fiber + Scheduler)的应用层 API
  • 它让开发者能够明确区分:哪些更新必须立刻执行,哪些可以让路

Reference

useTransition – React 中文文档

赞(0)
未经允许不得转载:171主机测评 » useTransition:如何让 React 更新“让路”
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址