React Hooks的丑陋一面( 三 )


因此,在提出有关动机的问题之后,让我们看一下我不喜欢的有关Funclass的其他内容 。
隐藏的副作用在Funclasses的 useEffect 实现中,最让我困扰的一件事,就是没有弄清楚某个组件的副作用是什么 。对于类,如果你想知道一个组件在挂载时做了什么,你可以很容易地检查 componentDidMount 中的代码或检查构造函数 。如果你看到一个重复的调用,你可能应该检查一下 componentDidUpdate,有了新的 useEffect 钩子,副作用可以深深地嵌套在代码中 。
假设我们检测到一些不必要的服务器调用,我们查看可疑组件的代码,然后看到以下内容:
const renderContacts = (props) => {const [contacts, loadMoreContacts] = useContacts(props.contactsIds);return (<SmartContactList contacts={contacts}/>)}这里没什么特别的,我们应该研究 SmartContactList,还是应该深入研究 useContacts?让我们深入研究一下 useContacts 吧:
export const useContacts = (contactsIds) => {const {loadedContacts, loadingStatus}= useContactsLoader();const {isRefreshing, handleSwipe} = useSwipeToReresh(loadingStatus);// ... many other useX() functionsuseEffect(() => {//** 很多代码,都与一些加载联系人的动画有关 。*//}, [loadingStatus]);//..rest of code}好的,开始变得棘手 。隐藏的副作用在哪里?如果我们深入研究 useSwipeToRefresh,我们将看到:
export const useSwipeToRefresh = (loadingStatus) => {// ..lot's of code// ...useEffect(() => {if(loadingStatus === 'refresing') {refreshContacts(); // bingo! 我们隐藏的副作用}}); //<== 我们忘记了依赖项数组!}我们发现了我们的隐藏效果,refreshContacts 会在每个组件渲染时意外地调用fetch contacts 。在大型代码库和某些结构不良的组件中,嵌套的 useEffect 可能会造成麻烦 。
我并不是说你不能用类编写糟糕的代码,但是Funclasses更容易出错,而且没有严格定义生命周期方法的结构,更容易做糟糕的事情 。
膨胀的API通过在类的同时增加钩子API,React的API实际上增加了一倍 。现在每个人都需要学习两种完全不同的方法,我必须说,新API比旧API晦涩得多 。一些简单的事情,如获得之前的props和state,现在都成了很好的面试材料 。你能写一个钩子获得之前得 props 在不借助google的情况下?
像React这样的大型库必须非常小心地在API中添加如此巨大的更改,这样做的动机甚至是不合理的 。
缺乏说明性在我看来,Funclass比类更混乱 。例如,要找到组件的切入点就比较困难——用classes只需搜索 render 函数,但用Funclasses就很难发现主return语句 。另外,要按照不同的 useEffect 语句来理解组件的流程是比较困难的,相比之下,常规的生命周期方法会给你一些很好的提示,让你知道自己的代码需要在哪里寻找 。如果我正在寻找某种初始化逻辑,我将跳转(VSCode中的cmd + shift + o)到 componentDidMount,如果我正在寻找某种更新机制,则可能会跳到 componentDidUpdate 等 。通过Funclass,我发现很难在大型组件内部定位 。
约定驱动的API钩子的主要规则(可能也是最重要的规则)之一是使用前缀约定 。
就是感觉不对你知道有什么不对劲的感觉吗?这就是我对钩子的感觉 。有时我能准确地指出问题所在,但有时只是一种普遍的感觉,即我们走错了方向 。当你发现一个好的概念时,你可以看到事情是如何很好地结合在一起的,但是当你在为错误的概念而苦恼的时候,发现你需要添加更多更具体的东西和规则,才能让事情顺利进行 。
有了钩子,就会有越来越多奇怪的东西跳出来,有更多“有用的”钩子可以帮助你做一些琐碎的事情,也有更多的东西需要学习 。如果我们需要这么多的utils在我们的日常工作中,只是为了隐藏一些奇怪的复杂,这是一个巨大的迹象,说明我们走错了路 。
几年前,当我从Angular 1.5转到React时,我惊讶于React的API是如此简单,文档是如此的薄 。Angular曾经有庞大的文档,你可能要花上几天的时间才能涵盖所有内容——消化机制、不同的编译阶段、transclude、绑定、模板等等 。光是这一点就给我很大的启示,而React它简洁明了,你可以在几个小时内把整个文档看一遍就可以了 。在第一次,第二次以及以后的所有次尝试使用钩子的过程中,我发现自己有义务一次又一次地使用文档 。
总结我讨厌成为聚会的扫兴者,但我真的认为Hooks可能是React社区发生的第2件最糟糕的事情(第一名仍然由Redux占据) 。它给已经脆弱的生态系统增加了另一场毫无用处的争论,目前尚不清楚钩子是否是推荐的使用方式,还是只是另一个功能和个人品味的问题 。


推荐阅读