2024-01-09·6 min read

为什么我也说 useEffect 是不好的设计

基于项目经验分析 useEffect 的设计问题,以及为什么建议在项目中禁止使用它

ReactHooks

最近X上鱿鱼丝转发一条推,又发起了一波vue大战react的理念大战。

让人不禁感慨难道这就是前端娱乐圈的年更节目吗。

争论点又来到框架心智负担,作为框架用户,到底怎么才算更好用。

由于框架的学习使用,每个人的使用频率,场景,都截然不同,能不吵就有鬼了。

何必踩低一头,认为自己才是更高的那头。

python才是最好的语言(

不过争论结束的彩蛋就是,连续几波人都在抓着React连续两次执行UseEffect来喷。

  • 人家就是这样设计的,dev模式下就会执行出两边
  • 你需要保证执行两遍也能正确的解决所谓的副作用

因为这个之前有研究,所以让我想了一下自己的看法。

之前在用了Hook一段时间后,我就跟另外几个人讨论过这个useEffect的问题

最后结论就是,不要在项目中使用useEffect.

这个结论是基于一些历史hook代码维护,线上项目bug的经验得到的。

第一个重要的原因是

  1. 刚接触hook的react新手无法理解useEffect设计本身初衷,会出现滥用useEffect,混合使用的情况。
  • 典型就是把useEffect当成类似 propsupdate, vue中的$watch的思路来使用,变成了一种订阅listener的写法
    • 这种写法一旦混合几种if条件的业务逻辑,整个回调函数就会失去可读性和独立含义。而且极易出现未覆盖的边界条件,因为useEffect可不是只执行一次。
    • 最糟糕的是这种代码需要从整个页面数据流去重构,在修bug的时候如果这么做,需要耗费大量心力。背负重构的心智和bug风险。
    • 当里面如果依赖的函数使用了useCallBack,那整个复杂度会更高。这也是为什么我说useCallback也是一个失败的设计
  • 第二种思路和前面类似,也是类似react class和vue带来的基础思路,更是页面设计中的标准思路,取代生命周期
    • 取代生命周期的问题最大的问题是:看代码的人要理解你在模仿某个生命周期。其次的问题是在修业务需求bug的时候,会在里面融入一些其他的逻辑。
    • 第二的问题就是它本来就不是为这个设计的,会出现大量的边界情况。
    • 怎么办就是用成熟的类似ahooks的库来取代这部分逻辑,明确某些是useMount去做的。事实上你看他们模仿生命周期钩子的实现,也包含了一些边界情况处理
  • 项目永远会有新人,也总有使用React的新人。与其科普一大堆抽象的自己都觉得勉强的概念,还不如直接禁止使用
  1. 第二点想说的其实就是维护相关的,其实前面已经提到了。这里指的维护一个是 抽象复用,一个是修bug/需求变更