如何封装可复用的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
相关产品推荐
相关产品推荐

