WHAT - React startTransition vs setTimeout vs debounce

文章目录

先给结论

setTimeout / debounce = 时间层面的延迟

startTransition = UI 优先级 & 可中断调度

它们解决的是 完全不同的问题

先给一张总对照表

维度 setTimeout debounce startTransition
本质 JS 定时器 JS 定时策略 React 调度语义
是否理解 UI
是否可中断
是否降低计算次数
是否防抖
是否解决卡输入 ⚠️ 部分
React 推荐 ⚠️

一、setTimeout:只是"往后丢一会儿"

代码

ts 复制代码
setTimeout(() => {
  setList(filter(data))
}, 0)

实际发生了什么?

  • 把任务放进 macrotask queue
  • 当前 call stack 执行完再跑
  • 但一旦开始执行,就不能被打断

为什么不能解决卡顿?

复制代码
输入
↓
JS 空闲
↓
setTimeout callback 开始
↓
filter(data) 占满 500ms
↓
输入仍然卡

它只是换了个时间点卡你

什么时候还能用?

  • 非 UI 逻辑
  • 低优先级副作用
  • 日志 / 打点

二、debounce:减少执行次数,不是调度

代码

ts 复制代码
const debouncedFilter = debounce((v) => {
  setList(filter(data, v))
}, 300)

它解决的是什么?

"你别每次都算"

  • 用户输入 10 次
  • debounce 后只算 1 次

它没解决什么?

  • 一旦真的执行
  • filter(data) 仍然是同步的
  • 仍然会卡主线程

debounce = 减少次数,不是让 UI 优先

debounce 的适用场景

场景 是否合适
请求接口
自动保存
搜索接口
本地大计算

三、startTransition:React 级别的"让路"

代码

ts 复制代码
startTransition(() => {
  setList(filter(data))
})

它到底做了什么?

React 在内部标记:

"这次更新可以被打断"

然后:

  • 输入事件 → 高优先级
  • transition 更新 → 低优先级
  • React 在空闲时间切片执行

时间线对比(非常关键)

setTimeout / debounce

复制代码
filter 开始
↓
500ms 主线程占满
↓
输入卡

startTransition

复制代码
filter 执行一部分
↓
用户输入
↓
React 中断 filter
↓
更新 input
↓
继续 filter

这是本质差异

四、三者最容易搞混的一点

startTransition 不会减少计算量

ts 复制代码
filter(data) // 还是会算

它只是:

  • 不一次性算完
  • 不阻塞 urgent 更新

五、正确的组合方式(生产级)

debounce + startTransition(最强)

ts 复制代码
const onChange = debounce((value) => {
  startTransition(() => {
    setList(filter(data, value))
  })
}, 200)

既少算,又不卡

错误组合(常见)

ts 复制代码
startTransition(() => {
  debounce(() => setList(...), 300)()
})

完全没意义。

六、一个表格搜索的真实决策树

输入 → 表格过滤 → 10000 行

问题 答案
每次输入都要算吗?
能不能晚点算?
用户在 input 框输入必须立即显示文字吗?

debounce + startTransition

七、为什么 React 团队不推荐 setTimeout?

因为:

  • 它绕过 React Scheduler
  • React 无法协调更新
  • 在 Concurrent 模式下是"黑盒"

八、用一句工程化标准帮你记住

JS 时间工具(setTimeout / debounce)

管"什么时候执行"

React 工具(startTransition)

管"谁先执行"

九、最后一段"刻进脑子"的话

setTimeout:

"等会再卡你"

debounce:

"少卡几次"

startTransition:

"先让用户动起来"

相关推荐
文心快码BaiduComate2 分钟前
Comate Spec Mode能力升级:让复杂任务开发更可控、更稳定
前端·后端
前端付豪6 分钟前
实现 AI 回复支持 Markdown 渲染
前端·人工智能·markdown
阳火锅17 分钟前
鳌虾 AoCode:重新定义 AI 编程助手的下一代可视化工具
前端·人工智能·架构
拾贰_C20 分钟前
【node】node彻底卸载删除
前端
SuperEugene21 分钟前
Vue3 组合式函数(Hooks)封装规范实战:命名 / 输入输出 / 复用边界 + 避坑|Vue 组件与模板规范篇
开发语言·前端·javascript·vue.js·前端框架
芝士麻雀23 分钟前
掌握 .claude/ 目录:让 Claude Code 真正懂你的项目
前端·后端
cmd25 分钟前
JS深浅拷贝全解析|常用方法+手写实现+避坑指南(附完整代码)
前端·javascript
进击的尘埃25 分钟前
AbortController 实战:竞态取消、超时兜底与请求生命周期管理
前端·javascript
张一凡9326 分钟前
我用 Zustand 三年了,直到遇见 easy-model...
前端·javascript·react.js
张元清27 分钟前
React 拖拽:无需第三方库的完整方案
前端·javascript·面试