React18 防抖节流新实现
导读
React18 起新加入了 useTransition
方法,
这个方法能解决什么问题,我们又如何使用它实现更优秀的产品体验?
既然文章标题说到了“防抖节流”,那这个方法和防抖节流有什么关系呢,会是同样技术思路的内部封装吗?
我们从防抖节流这项前端技术人必备的小技巧切入,来看看新方法 useTransition
的面纱。
再谈防抖节流
在绝大多数的产品交互中都都存在着两种数据反馈。一种是当我点击一个按钮,我希望它给我一份最新的数据;另一种是当我不断点击一个按钮的时候,我希望它始终给我最新的数据。在用户的角度,这两者的体验是具有一致性的,即当我“发生动作”时,我都希望尽快拿到最新的反馈结果。但在技术上,这两者是有巨大不同的,在 web 的世界里,数据响应是异步的,当动作持续发生时,如何让最新结果更快地反馈到用户,既需要考虑数据请求触发的优化,也需要考虑重复渲染成本的优化。
所以,我们引入两个概念来区分。我们把直接的交互反馈叫做「紧急更新」,典型的场景如点击按钮提交数据;把可能持续性触发的交互反馈叫做「过渡更新」,典型的场景如持续拖拽浏览器窗口重算布局、输入框持续输入触发联想请求。
如果技术研发中不关注对「过渡更新」的处理,那么不同严重程度上都会造成
- 大量高频请求造成的服务器开销
- 重复渲染计算造成的卡顿
- 在用户网络稍差的情况的持续“卡顿”
然而在 React17 及之前的版本,防抖节流是没有内置的解决方案的,需要用户手动实现或是利用第三方库来处理,所以我们常常看到很多线上项目理所当然地“偷懒”了。毕竟各位研发的电脑都是高配置,在没有强规范和足够的环境引导下,很难说提升整个团队对外的基础能力,当框架去推动这件事,就意味着所有上层应用都能往交互体验更好地走一步。
React18 中的防抖节流
虽然从开篇到现在我依然在提防抖节流,但 React18 中的新方法 useTransition
并不是防抖节流。
为什么这么说呢,因为「防抖节流」是一个手段,一个解决问题的技术方案,它既不是场景、也不是问题。真正的问题是如何优化过渡更新,以减少重算和提升效率,最终达到一个更好的体验。
让我们来回顾一下防抖和节流:
- 防抖的思路是限定时间等待状态稳定,举个例子就像 等电梯关门,一旦有一个人进来就需要再等1分钟才关门。
- 节流的思路是固定间隔时间执行,举个例子就像 等红灯通行,每等1分钟的红灯过后再通行。
你可能也发现了,不管防抖还是节流都有一个问题是,他们依赖一个研发设定的「间隔时间」,这意味着我们(研发)需要评估和猜测绝大部分用户在多少间隔时间是合适的,但事实是,不同的电脑性能、不同的网络状态所面临的瓶颈是天差地别的,比如在我们优秀的电脑上查看自己研发的产品就不会卡,对吧
新的实现 useTransition
正解决了这一问题,实现了根据用户本机的实际情况进行“充足” 的计算。其底层是 React18 对其所有工作进行每隔5毫秒的拆分和短暂挂起以让浏览器执行其他工作,并且优化了渲染队列,更高效地对新渲染需求进行处理。
使用案例
方法解释
一个基础调用是这样的
1 | import { useTransition } from 'react'; |
startTransition
是一个函数,用它来包装需要过渡/延迟更新的内容
isPending
是一个布尔值,用它来判断这种过渡/延迟更新是否正在进行
在上面这个代码段中,3000ms 表示如果获取数据响应超过了这个时间并且有下一个更新,React 将中断当前的更新。当然在这个案例中,你也同样可以选择用 isPending 对 button 进行 disabled 的处理。
查看完整的官方案例,展示了在反复触发点击获取数据后如何更优的更新渲染结果
升级到 React18 的 createRoot 形式
截至 21/08 是 alpha 版本,预计如果你看到这篇内容是在 21/11 之后,请自行查下最新包的升级方式
1 | yarn add react@alpha react-dom@alpha |
找到根节点注入的方式并修改
将原本的 render
方法更新为 createRoot
,React18 中的大部分新特性都需要改到这个并发模式
1 | // index.js before |
实现一个实时输入搜索
1 | import React, { useState, useTransition } from "react"; |
延伸:更新阻断带来的隐患
由于 Transition
的实现中基于多更新任务的对比计算和中断,在大体量的更新内容下可能有一定的风险性,需要进一步测试。目前测试的代码场景是简明扼要的,真实场景实际关联的组件量很可能众多而复杂,这种依赖于短时间对比计算的设计可能有一定的风险,这种场景在技术方案上或许还是更适合新的 Suspense
方案
延伸:开发小技巧1 —— 人为制造卡顿
通过 DevTool 可以调整模拟更差的网络情况和 CPU 情况,开始录制后的操作可能得到一份十分痛苦的产品体验