如何优化React Query条件调用多查询的冗余代码
优化React Query多实例冗余代码的几种方案
针对你当前的代码冗余问题,除了条件设置请求URL,还有以下几种优化思路,最终都能实现只返回一组{data, isLoading, isError}状态:
1. 动态配置单个useQuery实例
直接根据路由参数动态生成queryKey、queryFn以及数据转换逻辑,只用一个useQuery实例就能覆盖两种场景,彻底消除重复代码:
const { language, difficulty, source } = props.match.params; const { data, isLoading, isError } = useQuery({ // 动态生成唯一查询键,区分不同source和参数 queryKey: [`test-${source}-${language}`, difficulty], queryFn: async () => { let response; if (source === "api") { response = await fetch( `${BASE_URL}${API_URLS.GET_QUIZ}/?languages=${language}&level=${difficulty}` ); } else if (source === "intern") { response = await fetch( `${BASE_URL}${API_URLS.TEST}/${language}` ); } const rawData = await response.json(); // 针对intern场景做数据转换 return source === "intern" ? rawData?.questions || [] : rawData; }, // 参数变化时queryKey自动触发重查,无需手动控制enabled enabled: true, }); // 直接使用useQuery返回的状态,无需额外useEffect同步
这个方案的优势是完全复用单个useQuery的生命周期,逻辑紧凑,路由参数变化时自动触发重新查询,省去了额外的状态同步代码。
2. 使用useQueries合并请求并映射结果
如果需要保留两个请求的独立配置(比如后续可能需要同时启用),可以用useQueries批量管理多个查询,再通过逻辑映射出统一状态:
const { language, difficulty, source } = props.match.params; const queries = useQueries({ queries: [ { queryKey: [`test-api-${language}`, difficulty], queryFn: () => fetch( `${BASE_URL}${API_URLS.GET_QUIZ}/?languages=${language}&level=${difficulty}` ).then(res => res.json()), enabled: source === "api", }, { queryKey: [`test-intern-${language}`], queryFn: () => fetch( `${BASE_URL}${API_URLS.TEST}/${language}` ).then(res => res.json()), enabled: source === "intern", }, ], }); // 映射出统一的对外状态 const activeQuery = source === "api" ? queries[0] : queries[1]; const data = source === "intern" ? activeQuery.data?.questions || [] : activeQuery.data; const isLoading = activeQuery.isLoading; const isError = activeQuery.isError;
这个方案适合需要同时维护多查询配置,但又要对外暴露统一状态的场景,灵活性更高。
3. 封装自定义Hook抽离逻辑
把整个查询逻辑封装成自定义Hook,组件只需要传入路由参数,直接拿到统一状态,让组件代码更干净:
// 自定义Hook:useTestData.js export const useTestData = ({ language, difficulty, source }) => { return useQuery({ queryKey: [`test-${source}-${language}`, difficulty], queryFn: async () => { let response; if (source === "api") { response = await fetch( `${BASE_URL}${API_URLS.GET_QUIZ}/?languages=${language}&level=${difficulty}` ); } else if (source === "intern") { response = await fetch( `${BASE_URL}${API_URLS.TEST}/${language}` ); } const rawData = await response.json(); return source === "intern" ? rawData?.questions || [] : rawData; }, enabled: !!source, }); }; // 组件中使用 const { language, difficulty, source } = props.match.params; const { data, isLoading, isError } = useTestData({ language, difficulty, source });
这种方式把业务逻辑从组件中抽离,不仅让组件更简洁,还方便后续在其他组件复用这段查询逻辑。
内容的提问来源于stack exchange,提问作者user3568611
相关产品推荐
相关产品推荐

