1 引言
与组件生命周期绑定的 Utils 非常适合基于 React Hooks 来做,比如可以将 “发请求” 这个功能与组件生命周期绑定,实现一些便捷的功能。
这次以 @umijs/use-request 为例子,分析其功能思路与源码。
2 简介
@umijs/use-request 支持以下功能:
默认自动请求:在组件初次加载时自动触发请求函数,并自动管理
loading
,data
,error
状态。手动触发请求:设置
options.manual = true
, 则手动调用run
时才会取数。轮询请求:设置
options.pollingInterval
则进入轮询模式,可通过run
/cancel
开始与停止轮询。并行请求:设置
options.fetchKey
可以对请求状态隔离,通过fetches
拿到所有请求状态。请求防抖:设置
options.debounceInterval
开启防抖。请求节流:设置
options.throttleInterval
开启节流。请求缓存 & SWR:设置
options.cacheKey
后开启对请求结果缓存机制,下次请求前会优先返回缓存并在后台重新取数。请求预加载:由于
options.cacheKey
全局共享,可以提前执行run
实现预加载效果。屏幕聚焦重新请求:设置
options.refreshOnWindowFocus = true
在浏览器refocus
与revisible
时重新请求。请求结果突变:可以通过
mutate
直接修改取数结果。加载延迟:设置
options.loadingDelay
可以延迟loading
变成true
的时间,有效防止闪烁。自定义请求依赖:设置
options.refreshDeps
可以在依赖变动时重新触发请求。分页:设置
options.paginated
可支持翻页场景。加载更多:设置
options.loadMore
可支持加载更多场景。
一切 Hooks 的功能拓展都要基于 React Hooks 生命周期,我们可以利用 Hooks 做下面几件与组件相关的事:
存储与当前组件实例绑定的 mutable、immutable 数据。
主动触发调用组件 rerender。
访问到组件初始化、销毁时机的钩子。
上面这些功能就可以基于这些基础能力拓展了:
默认自动请求
在组件初始时机取数。由于和组件生命周期绑定,可以很方便实现各组件相互隔离的取数顺序强保证:可以利用取数闭包存储 requestIndex,取数结果返回后与当前最新 requestIndex 进行比对,丢弃不一致的取数结果。
手动触发请求
将触发取数的函数抽象出来并在 CustomHook 中 return。
轮询请求
在取数结束后设定 setTimeout
重新触发下一轮取数。
并行请求
每次取数时先获取当前请求唯一标识 fetchKey
,仅更新这个 key 下的状态。
请求防抖、请求节流
这个实现方式可以挺通用化,即取数调用函数处替换为对应 debounce
或 throttle
函数。
请求预加载
这个功能只要实现全局缓存就自然支持了。
屏幕聚焦重新请求
这个可以统一监听 window action 事件,并触发对应组件取数。可以全局统一监听,也可以每个组件分别监听。
请求结果突变
由于取数结果存储在 CustomHook 中,直