React 自定义hooks最佳实践

1. 背景

react hooks推出已经有一段时间了,而自定义hooks在hooks中其实是非常关键的一环,它是抽离业务逻辑和UI逻辑,复用代码的关键,因此在使用上相对于其他hooks不易掌握,你可能在开发中经常会遇到以下问题

  1. 我该什么时候使用自定义hooks?
  2. 使用自定hooks时应该传入什么参数,又返回出什么值?
  3. 为什么使用自定义hooks,我的代码逻辑好像没有变简洁?

为了解决以上疑问,下面我会结合业务的实际场景,通过几个案例,来跟大家分享自定义hooks中的一些实践与经验
注:本文默认读者具备一定的react基础

2. 案例一:Tabs组件

需求一:有一个Tab选项和内容区,tab的切换,会改变tabId,需要重新拉取接口数据,用以展示不同的内容

class实现

我们使用class组件实现一下,来借以发现class组件中存在的一些问题
React 自定义hooks最佳实践_第1张图片

我将这个功能抽成了三个组件

  • Tab:负责切换Tab
  • ContentContainer: 负责处理数据逻辑
  • Content:负责渲染
    为什么要这么拆分的原因:将包含业务逻辑的容器组件和UI展示部分的展示组件剥离开,利于代码的复用,详细可参考:medium

原有的class组件模式,通常是将组件拆分为UI组件和容器组件,容器组件部分处理数据逻辑,套在需要使用到该逻辑的组件上,从而达到复用代码逻辑的目的。

因此在处理Content的时候,我将其拆成了两个组件

  • 只负责渲染的Content组件
  • 只负责逻辑处理的ContentCantainer组件
    为了复用,我们只能通过props的形式,做一层嵌套,像React中的高阶组件就是通过这种模式来实现代码逻辑的复用。
    但这种模式存在一定缺陷,组件非常复杂的时候,如果每次都通过嵌套拆分的模式来复用代码,会形成很深的组件层级和嵌套逻辑,这会给开发带来不少麻烦。而hooks的出现就解决了这个问题

hooks改造

针对之前遇到的问题,我们使用hooks进行改造
React 自定义hooks最佳实践_第2张图片

在class组件中,为了复用状态,我们将Content拆成了两个组件,并形成了嵌套。
而在hooks中,我们只使用了一个组件和一个自定义hooks

  • useContent:自定义hooks,负责处理逻辑,将状态返回给外界组件
  • Content:UI组件,负责渲染
    与class不同的是,这两者并没有形成嵌套关系,而是扁平化,自定义的useContent,负责将组件逻辑抽了出来,只暴露给Content所需的状态

案例二:Table组件

需求二:实现一个表格组件,需要分页功能,切换不同页面时,加载不同的数据
React 自定义hooks最佳实践_第3张图片

常规实现

这个需求,在后台十分常见,比较常见的写法如下:
React 自定义hooks最佳实践_第4张图片

在组件中我们不仅维护了Table组件的UI状态,也同时维护了Table组件的业务逻辑,定义了多个状态
loading, dataSource , current, total
几乎每个表格组件都会包含上述的业务逻辑,此时我们就可以将业务逻辑使用Hooks的方式剥离出来,来实现复用的目的。

hooks改造

在编写 useTableHooks 的时候,我们需要注意两个地方

  1. 需要将请求接口的函数作为参数传入hooks中,且该函数需要约定固定的入参和返回值
  2. 原因1:因为每个Table组件的网络请求都不一样,所以它是属于Table组件本身的逻辑,并不是useTableHooks 的逻辑,因此请求接口的函数需要在Table组件中定义
  3. 原因2:约定固定参数和返回值是为了统一在hooks中处理数据
  4. 监听表格切换的change函数,需要作为useTableHooks的返回值暴露出来,而不是在Table组件中监听change

平时在写业务逻辑的时候,我们较少的会使用这种写法(将函数作为参数传入,将函数作为返回值传出),因此对于这两个地方需要额外的注意。

Table组件代码如下:
React 自定义hooks最佳实践_第5张图片

useTableHooks组件代码如下:
React 自定义hooks最佳实践_第6张图片

可以看到通过自定义hooks的改造,成功的将UI逻辑和业务逻辑给分离开来,在其他地方再次使用到表格组件时,就可以直接使用 useTableHooks 去处理分页逻辑。
整个组件变得就更加简洁可复用了。

思考:业务要求table组件需要添加查询表单,那么自定义hooks应该如何扩展呢?
React 自定义hooks最佳实践_第7张图片

总结

通过上面两个案例,我们可以回答最开始的几个问题了

  1. 我该什么时候使用自定义hooks?
    • 发现某处业务逻辑重复使用时,可将业务逻辑抽离开
    • 组件比较复杂时,可通过自定义hooks拆分组件逻辑,简化代码
  2. 使用自定hooks时应该传入什么参数,又返回出什么值?
    • 传参和返回值是比较灵活的,需要注意的是,不仅能传常规的数据类型,还能传递函数对象
  3. 为什么时候自定义hooks,我的代码好像没有变简洁?
    • 要理解UI组件和容器组件这两个概念,恰当的抽离业务逻辑部分,保留组件的UI部分,组件复杂时拆分可能也有一定的难度,过度设计会导致组件更难维护,因此要把控好度

你可能感兴趣的:(react,react.js,前端,javascript)