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:

"先让用户动起来"

相关推荐
用户938515635074 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformer.js 全链路实战
前端·设计模式·typescript
CodeSheep4 小时前
稚晖君公司人事大变动,来了!
前端·后端·程序员
鱼樱前端4 小时前
用 AI 做内容变收入
前端·人工智能·ai编程
浮生望4 小时前
React + TypeScript 组件设计进阶:从类型约束到无状态组件的三次进化
前端
90后的晨仔5 小时前
Mac 开发 uni-app 终极方案:让安卓模拟器彻底脱离 Android Studio 独立运行
前端·vue.js
90后的晨仔5 小时前
别再搞混了!uni-app 中 node_modules 和 uni_modules 到底是什么关系?
前端
kyriewen6 小时前
面试官问"这段逻辑为什么这样写"——我才发现,这半年我写的代码,我自己都解释不了
前端·javascript·面试
谢小飞6 小时前
大文件上传很难?学会这招,GB文件秒传不是梦
前端·node.js
程序员黑豆7 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
To_OC7 小时前
别只拿 useRef 绑 DOM 了,搭配 Web Worker 解决页面卡顿才是真的香
前端·react.js·dom