当前位置: 首页 > 工具软件 > react-query > 使用案例 >

React-query高效封装进阶高级向技巧(向模板代码说No/内含学习路线)

葛威
2023-12-01

前言

本文为 react-query 进阶高级技巧,适合对 react-query 已经熟练使用的人,关于 react-query 基础内容本文将不会再提,高阶读友可放心阅读。

假如你是零基础者,以下历史文章可供追溯:

《 React Api请求最佳实践react-query3使用教程(比swr更好用更强大)》

通过本文你可以对 react-query 形成一个初步认识,但接触面不会超过 50% ,在这之后你可以进行自己的学习精进到 80% 的认知。

《 Api请求库react-query之缓存出神入化——作为全局状态管理 》

通过本文你可以从另一个比较 hack 的角度了解 react-query,加深对 cache 的认知。

《 react-query在项目中的架构封装设计(大量实践经验)》

通过本文你可以进一步规范提升你的 RQ 编码技术,精进技巧,让代码封装的更加优美,提高可维护性和可拓展性。

正文

我们这里要提的是,如何避免 react-query 的模板代码,快速把 RQ 接入?

《 react-query在项目中的架构封装设计(大量实践经验)》 一文中我们知道,RQ 进阶高级封装是需要很多模板代码的,繁杂紧迫的业务要求我们又要兼顾快速编码,又要高可维护,如何做到既要又要还要?

答案是 去其槽粕,取其精华

我们把使用分为两类,一类是 查询( useQuery ),一类是请求( useMutation )。

先看一个 查询( useQuery ) 的 case。

useQuery

接口层:

export interface IGetSearchResultParams {
  key: any
}

export interface ISearchResult {
  key: any
}

export const getSearchResult = async (params: IGetSearchResultParams) => {
  const res = await getSearchSome(`//domain.com`, params)
  return res?.data as ISearchResult | undefined
}

最需要注意的是你的 res?.data 可能为空!其他的我们不做多余说明。

RQ 层:

import { useQuery } from 'react-query'
import { isNil } from 'lodash'
import { IGetSearchResultParams, getSearchResult } from './path/to/api'

export const useSearchResult = (params?: Partial<IGetSearchResultParams>) => {
  return useQuery(
    ['useSearchResult', params],
    async () => {
      const data = await getSearchResult(params as any)
      // 你可能有一些其他固定逻辑在这里
      // ...
      return data
    },
    {
      enabled: !isNil(params), // 更严格的 case:!isNil(params) && !isNil(params?.xxx)
    }
  )
}

来看一下我们设计的用心:

  1. 入参使用 Partial 作用原入参,得到 Partial<IGetSearchResultParams> 这样可以避免入参传递可能报空,否则你还要再引导一遍这个 type 或 as any ,因为多数情况瀑布流数据我们的入参实际上是有的,但是 ts 会报空,你完全没必要在这方面浪费时间精力。

  2. RQ 的 key 方面,因为 RQ 天生支持对象,所以保证我们的 hooks 名互斥 + params 区分即可,也无需去抽离 key,加快业务编码速度。

  3. 最后最重要的安全性把控一定要做,保证数据流安全,最低限是做非 null / undefined 的处理,如果有其他重要参数,可多加判断。

实际上这个 RQ 的产出成本不到一分钟,由此以来 RQ 的模板成本便大幅减少!

useMutation

对于 改删 类请求我的看法是比较开放的,hooks 可抽离也可不抽离,但是查询最好抽离,提供一个参考的 case :

const modifyMutation = useMutation(async (params: IUpdateDataParams) => {
  const res = await updateDataApi(params)
  if (res?.code === 0) {
      message.success('成功')
      // refetch data
      someUseQuery.refetch()
      // other success callback
      // ...
      return
  }
  message.error('失败,请重试')
})

// 下面你可以使用
const data = modifyMutation.data
const loading = modifyMutation.isLoading

再次回归本意,mutation 终究还是一个比较定制化的东西,你去抽离也无法改变有多处业务虽然是一个 api 但是入参不同的定制化逻辑,而且有时信息提示也不同,抽离的收益并不大,特别是复杂的定制业务。

总结

RQ 在高级进阶后,我们尽量朝向减少模板代码的方向发展,我们要的是 RQ 帮我们管理状态的强大,和其具备的一些强大附属功能,但绝不能像 redux 一样给我们负收益了一大堆模板代码。

 类似资料: