React Hooks 并没有权威的设计模式,很多工作还在建设中,在这里我谈一下自己的一些看法。

    首先用 Hooks 开发需要抛弃生命周期的思考模式,以 effects 的角度重新思考。过去类组件的开发模式中,在 componentDidMount 中放置一个监听事件,还需要考虑在 componentWillUnmount 中取消监听,甚至可能由于部分值变化,还需要在其他生命周期函数中对监听事件做特殊处理。在 Hooks 的设计思路中,可以将这一系列监听与取消监听放置在一个 useEffect 中,useEffect 可以不关心组件的生命周期,只需要关心外部依赖的变化即可,对于开发心智而言是极大的减负。这是 Hooks 的设计根本。

    在这样一个认知基础上,我总结了一些在团队内部开发实践的心得,做成了开发规范进行推广。

    第一点就是 React.useMemo 取代 React.memo,因为 React.memo 并不能控制组件内部共享状态的变化,而 React.useMemo 更适合于 Hooks 的场景。

    第二点就是常量,在类组件中,我们很习惯将常量写在类中,但在组件函数中,这意味着每次渲染都会重新声明常量,这是完全无意义的操作。其次就是组件内的函数每次会被重新创建,如果这个函数需要使用函数组件内部的变量,那么可以用 useCallback 包裹下这个函数。

    第三点就是 useEffect 的第二个参数容易被错误使用。很多同学习惯在第二个参数放置引用类型的变量,通常的情况下,引用类型的变量很容易被篡改,难以判断开发者的真实意图,所以更推荐使用值类型的变量。当然有个小技巧是 JSON 序列化引用类型的变量,也就是通过 JSON.stringify 将引用类型变量转换为字符串来解决。但不推荐这个操作方式,比较消耗性能。

    这是开发实践上的一些操作。那么就设计模式而言,还需要顾及 Hooks 的组合问题。在这里,我的实践经验是采用外观模式,将业务逻辑封装到各自的自定义 Hook 中。比如用户信息等操作,就把获取用户、增加用户、删除用户等操作封装到一个 Hook 中。而组件内部是抽空的,不放任何具体的业务逻辑,它只需要去调用单个自定义 Hook 暴露的接口就行了,这样也非常利于测试关键路径下的业务逻辑。