You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何封装可复用的React Query Hooks?解决复用及报错问题

React Query 可复用Hook封装与逻辑分离方案

首先修正你代码里的两个关键错误:

1. 修正Hook调用方式

在page.js中,你直接引用了useCompanyInfo函数本身,而没有调用它。React Hook必须作为函数调用才能正常工作:

// page.js 修正后
import { useCompanyInfo } from '../hooks/useCompanyInfo'

const Page = () => {
  // 必须调用Hook函数
  const { data: companyInfo, isLoading, error } = useCompanyInfo()

  // 处理加载、错误状态
  if (isLoading) return <div>加载中...</div>
  if (error) return <div>请求失败:{error.message}</div>

  return <div>企业名称:{companyInfo?.name}</div>
}

export default Page

2. 修正查询函数传递方式

在dataHook.js中,你用箭头函数包裹fetchCompanyInfo时没有执行它,导致React Query调用的是一个返回函数的函数,而非实际的请求逻辑。直接传递fetchCompanyInfo即可:

// hooks/useCompanyInfo.js 修正后
import axios from 'axios'
import { useQuery } from 'react-query'

// 封装请求逻辑,处理响应数据(只返回需要的部分)
const fetchCompanyInfo = async () => {
  const res = await axios.get('http://127.0.0.1:8000/api/')
  return res.data
}

// 封装自定义Hook,集中管理查询key、请求函数和配置
export const useCompanyInfo = () => {
  return useQuery(
    'companyInfo', // 查询唯一标识,用于缓存管理
    fetchCompanyInfo, // 直接传递请求函数
    {
      // 可选:添加缓存、重试等配置,统一管理
      staleTime: 5 * 60 * 1000, // 5分钟内数据视为新鲜,不重复请求
      retry: 2 // 请求失败自动重试2次
    }
  )
}

实现类似Redux Slice的逻辑分离

要像Redux Slice那样按业务模块分离逻辑,你可以按以下方式组织代码:

按业务模块拆分Hook

在hooks目录下为每个业务模块创建独立的Hook文件,比如:

  • useCompanyInfo.js(企业基础信息)
  • useCompanyDetail.js(企业详情,带参数)
  • useProductList.js(产品列表)

每个Hook封装对应业务的请求逻辑、查询key和配置,组件只需调用Hook获取数据状态,无需关心请求细节。

带参数的可复用Hook示例

比如封装根据企业ID获取详情的Hook:

// hooks/useCompanyDetail.js
import axios from 'axios'
import { useQuery } from 'react-query'

const fetchCompanyDetail = async (companyId) => {
  const res = await axios.get(`http://127.0.0.1:8000/api/companies/${companyId}`)
  return res.data
}

export const useCompanyDetail = (companyId) => {
  // 查询key包含参数,确保不同ID对应独立缓存
  return useQuery(
    ['companyDetail', companyId],
    () => fetchCompanyDetail(companyId),
    {
      // 只有当ID存在时才触发请求
      enabled: !!companyId
    }
  )
}

组件调用时只需传入参数:

import { useCompanyDetail } from '../hooks/useCompanyDetail'

const CompanyDetailPage = ({ companyId }) => {
  const { data: detail, isLoading } = useCompanyDetail(companyId)

  if (isLoading) return <div>加载详情中...</div>
  return <div>企业地址:{detail?.address}</div>
}

核心优势

  • 逻辑集中管理:请求逻辑、缓存配置都在Hook中统一维护,避免组件重复代码
  • 缓存自动复用:React Query通过查询key自动复用缓存数据,无需手动同步状态
  • 组件专注UI:组件只需要处理加载、错误、数据渲染逻辑,无需关心请求细节

内容的提问来源于stack exchange,提问作者Luke.Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:50:28