最近在搞一个基于 AntPro 的管理端。除了把诸如多语言、动态主题配置、各种无用的依赖、文件、页面、配置等等都干掉了之后,我不禁盯着项目里的 dva 又陷入了沉思…

3 秒后,我决定也把它送到非洲去…

于是又是一顿猛如虎的操作(删配置,删依赖,删 models,删 connect,删 props 引用)后,看着清清爽爽的工程结构,我笑了。

如上图!所谓定义一个 hox model 就变成了是把 useRequest 的 data 和 run 导出,我看了看我的小天才手表,才花了一分钟不到。

所谓使用一个 model 就变得像是 use 一个 state 那么方便,配合 TypeScript 点起来属性也无比通畅:

不愧是下一代 React 状态管理器,从此解决了组件 props 的三大未解之谜:

  1. prop 是干啥的
  2. prop 从哪里来
  3. prop 要到哪里去

更让我欣慰的是,定义一些全局通用数据的时候,比如:省市县列表、某些到处使用的选择器数据,再也不用想这些数据的首次请求是放在 index.ts、还是 app.tsx、还是 global.ts、还是 basicLayout.tsx 等等所谓的入口文件哪个更科学的问题了。更不用每次都要在组件内 if update 了!

直接:

1
2
3
4
5
6
7
8
9
function Regions() {
const { data } = useRequest<Region[]>('base/regions')

return {
regions: data || [],
}
}

export default createModel(Regions)

是的,对外根本就不提供 update 方法!非 manual 模式的 useRequest 自动会在组件初次加载时候发起请求,而被 createModel 包装过的组件,全局也只会触发一次该 effect。如此你可以在任何组件内随意引,随意用,不用担心请求被发出去多次,也不用担心引用的数据是空的。

更有一个隐藏的好处是:即使是通用数据也有一定概率用不到,按照上述方式,配合一般脚手架都自带的懒加载和 tree shaking(只加载当前用到的 model,换句话说 model 一旦被加载就是会触发的)。这些通用数据也只会在真正需要的时候才会被请求(打开的某个页面展示的某个组件里 use 了通用 model

完。(或许会考虑把整个改造后的工程开源出来


2020/10/20 更:

某天你接到一个需求:希望某些页面被访问时某个数据永远是最新的!然而那个数据是基于 useRequet 的 hox model,如上文所说,它只会在整个网页的生命周期内触发一次请求。

换句话说,某个当时以为更新不会太频繁且会被到处引用的冷数据现在变成了热的。面对这种情况先不用着急去打产品经理,因为你打他的时间已经足够你改完了:

1
2
3
4
5
6
7
8
9
function useXData() {
const { data } = useRequest('/x')

return { xData: data }
}

// export default createModel(useXData)

export default useXData

是的,你只需要把 createModel 删了就好,因为基于 useRequest 的 useData 函数本身就是一个 hooks,且 useRequest 不做特殊配置时就是会在被引用的组件发生初次渲染时重新发起请求的。

所以,你只需要动这一个文件,改这一行代码,就搞定了这个需求。


 评论