将react-query的useQuery封装为通用API请求自定义钩子是否正确?
你的封装存在以下几个明显问题:
- 查询键(Query Key)设计不符合 React Query 规范
React Query 依赖查询键识别缓存、触发自动重新请求,你当前的查询键只包含了自定义的key和语言,没有把mode、params这些影响请求结果的变量纳入依赖,一旦params、mode发生变化,React Query 会直接返回旧缓存,不会发起新的请求,出现数据不符合预期的问题。另外统一加的getApi前缀没有实际意义,反而会增加缓存匹配的冗余。 - 参数拼接方式容错性极低
要求调用方传入拼接好的参数字符串,很容易出现特殊字符未转义、多参数漏加&、空参数多拼接&的问题,比如params为空时,你的URL会变成/api/xxx/?&lang_code=xxx的非法格式。 - 灵活性不足
你直接把useQuery的配置写死,调用方无法自定义缓存时间、重试次数、请求成功/失败回调等常用配置,遇到特殊需求只能改hook源码,扩展性很差。 - 请求地址硬编码
API域名直接写死在hook内部,不同环境(开发/测试/生产)切换域名时需要修改源码,维护成本高。 - 请求函数每次渲染重复创建
没有用useCallback包裹getApi函数,虽然不影响功能,但会产生不必要的性能开销。
优化后的参考实现:
import { useCallback } from 'react' import { useQuery } from '@tanstack/react-query' import axios from 'axios' import { useGetConfig } from './your-config-path' export function useGetApi(mode, params = {}, queryKeyExtra = [], queryConfig = {}) { const { config } = useGetConfig() // 从环境变量取域名,避免硬编码 const baseUrl = import.meta.env.VITE_API_BASE_URL || 'https://example.com/api' // 用URLSearchParams自动处理参数转义和拼接 const searchParams = new URLSearchParams(params) searchParams.append('lang_code', config.language) const url = `${baseUrl}/${mode}/?${searchParams.toString()}` // 完整查询键包含所有影响请求的变量,自动触发重请求 const queryKey = ['getApi', mode, params, config.language, ...queryKeyExtra] const getApi = useCallback(async () => { const { data } = await axios.get(url) return data }, [url]) return useQuery({ queryKey, queryFn: getApi, enabled: !!config.language, // 传入自定义配置,覆盖默认值 ...queryConfig }) }
调用示例:
const { isLoading, data: products, error } = useGetApi( 'products', { company_id: companyId }, [companyId], // 可自定义配置 { retry: 2, staleTime: 5 * 60 * 1000 } )
内容的提问来源于stack exchange,提问作者Masoud Tesna
相关产品推荐
相关产品推荐

