前端小记
首发于前端小记

React Hooks 之于 HoC 与 Render Props

在此之前,不了解 HoC 的同学请看 高阶组件 - React,不了解 Render Props 的同学请看 Render Props - React,都是官方文档,我贴的都是翻译链接。

总的来说,HoC 与 Render Props 都是不错的 React 或者 VDOM 框架中的代码组合思路,但现在 React 生态显然有了新欢: Hooks Introducing Hooks - React。具体 Hooks 是怎么玩的就不解释了。

Hooks 的出现使得原本很多很别扭的写法变得轻松,典型就是他可以取代掉 class 生命周期中大多数的功能,把更相关的逻辑放在一起,而非零散在各个生命周期实例方法中。

但也开始有了另一个问题: Do Hooks replace render props and higher-order components?

官方的回答说,在 HoC 或者 Render Props 只有一个 child 的情况下通常 hooks 是一个更简单的提供的方式。但我想,我们可以再深挖一下。


在 Hooks 之前,如果要做不同注入数据/状态之间的计算是挺操蛋的。

HoC 方案的典型思路是,在对原视图进行多次的 decorate 之后,再进行 mapProps 处理,将前面的多个数据进行一次中心化的计算。这是个特别函数式的操作,可能有一定的门槛;而且,这种方式的确与 render 距离太远了,以至于在 class 内部可能都得纠结一下各个 props 究竟是来自于哪里,如果有问题、问题又出自于哪里。

而另一种思路则是 Render Props, 就是把 HoC 包装为一个 JSX 组件,通过 function children 或者 render props 将状态递交给下一层,典型就像 motion 库中做的那样;问题就在于如果有很多的组件依赖,就会一层套一层地形成 JSX 中的嵌套地狱。而且,这种方式显然太深入到 render 过程中了,一些简单的操作却需要嵌套一层 JSX 也是挺痛苦的。

而上面不管是哪种方式,都还是将各个数据 / 状态之间的关系给拉远了。

Hooks 就解决了这个问题,就像 async / await 之于 Promise 的关系那样。


但这显然并不意味着 Hooks 就能取代了 HoC 以及 Render Props,因为他们其实还是有着各自的优势所在。

  • HoC 可以做到很轻松地外部协议化注入功能到一个基础 Component 中,所以可以用来做插件。就像 react-swipeable-views 中的 autoPlay HoC 那样,这个功能特性直接放到主库里面感觉不太合适,但可以通过注入状态化的 props 的方式进行扩展。这种特性使得 HoC 特别适合用来做基础组件的插件,也适合用于做 Adapter 层。而反观 Hooks 中间的处理过程则一定会与目标组件强依赖。这不是 Hooks 的缺陷,但 Hooks 显然并不是设计来进行插件注入的。
  • HoC 的方式可以天然地进行组件的分层以及组合,并且这种分层基本都可以描述为状态注入以及 props mapping 的过程。并且,这个分层过程可以描述为函数式的 compose,这对于其中的配置及顺序管理非常有利。
  • 而看看 Render Props,其使用时天然的就是 JSX 的一部分,那就意味着他JSX 中的逻辑计算来进行其中参数的管控,也可以通过 VDOM 中的 diff 特性提供性能上的优化。虽然嵌套地狱似乎不是什么好事,但树状结构本身就是嵌套的,XML Like 的语法却依然更合适用于描述树状结构以及其中的决策过程。
  • Render Props 还是非常天然而简单的逻辑,在其中可以放心大胆地进行各种 map, if-else, && 等各类操作。而 Hooks 却不是,他的设计机制使得使用起来与调用顺序强相关,那限制就多。

所以,Hooks 个人看来更多是对原有的 HoC 以及 Render Props 方案的补充,填补了原本两边都不擅长的部分。他的写法天然地可以让代码更加紧凑,更适合做 Controller 或者需要内聚的相关逻辑。


总结下:

  • Hooks 可以优化 render 的前置逻辑处理,也适合用于取代 class extend 的写法;
  • HoC 更多是个从外注入的方案,也适合用来做插件;
  • Render Props 可以在树状 VDOM 的渲染流程上有更多的自由度;

当然 Hooks 依然被赋予了极高的价值,因为,我为何不能用 Hooks 的方式来写 HoC 以及 Render Props? 这中间具体的使用,有着极高的灵活性,需要根据具体情况具体分析。

发布于 2019-04-17

文章被以下专栏收录