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组件中存在的一些问题
在这里插入图片描述

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

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

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

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

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

hooks改造

针对之前遇到的问题,我们使用hooks进行改造
在这里插入图片描述

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

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

案例二:Table组件

需求二:实现一个表格组件,需要分页功能,切换不同页面时,加载不同的数据
在这里插入图片描述

常规实现

这个需求,在后台十分常见,比较常见的写法如下:
在这里插入图片描述

在组件中我们不仅维护了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组件代码如下:
在这里插入图片描述

useTableHooks组件代码如下:
在这里插入图片描述

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

思考:业务要求table组件需要添加查询表单,那么自定义hooks应该如何扩展呢?
在这里插入图片描述

总结

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

  1. 我该什么时候使用自定义hooks?
    • 发现某处业务逻辑重复使用时,可将业务逻辑抽离开
    • 组件比较复杂时,可通过自定义hooks拆分组件逻辑,简化代码
  2. 使用自定hooks时应该传入什么参数,又返回出什么值?
    • 传参和返回值是比较灵活的,需要注意的是,不仅能传常规的数据类型,还能传递函数对象
  3. 为什么时候自定义hooks,我的代码好像没有变简洁?
    • 要理解UI组件和容器组件这两个概念,恰当的抽离业务逻辑部分,保留组件的UI部分,组件复杂时拆分可能也有一定的难度,过度设计会导致组件更难维护,因此要把控好度
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React自定义Hooks是一种自定义React Hook函数,用于在无需编写类组件的情况下,复用和共享状态逻辑。通过使用自定义Hooks,我们可以将组件中的逻辑提取出来,以便在多个组件之间共享和重用。引用中提到的HookReact 16.8新增的特性,它可以让我们在函数组件中使用状态和其他React特性,而无需编写类组件。而引用中的useUpdateEffect是一个自定义React Hook,它类似于React的useEffect,但是只在组件更新时执行副作用操作,忽略了组件的初始渲染阶段。 使用React自定义Hooks的步骤如下: 1. 创建自定义Hook函数,函数名以"use"开头,例如"useCustomHook"。 2. 在自定义Hook函数中,可以使用其他React Hooks和自定义逻辑来实现所需的功能。 3. 在组件中通过调用自定义Hook函数来使用该Hook,以获取状态和执行副作用操作。 下面是一个示例,展示如何创建和使用一个自定义Hook来管理计数器的状态: ```javascript // 自定义Hook import { useState } from 'react'; function useCounter(initialValue) { const [count, setCount = useState(initialValue); const increment = () => { setCount(count + 1); }; const decrement = () => { setCount(count - 1); }; return { count, increment, decrement }; } // 使用自定义Hook的组件 import React from 'react'; import useCounter from './useCounter'; function Counter() { // 使用useCounter自定义Hook,获取计数器的状态和操作函数 const { count, increment, decrement } = useCounter(0); return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); } ``` 在上述示例中,我们创建了一个名为useCounter的自定义Hook函数,它使用useState来管理计数器的状态,并提供了increment和decrement函数来增加和减少计数器的值。然后,我们在Counter组件中使用useCounter来获取计数器的状态和操作函数,并展示计数器的值以及按钮来增加和减少计数器的值。 通过使用React自定义Hooks,我们可以轻松地复用和共享状态逻辑,使代码更加可维护和可扩展。通过创建自定义Hooks,我们可以将组件的逻辑分离出来,提高代码的重用性和可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值