React中Context Provider内axios+react-query请求失效问题求助
问题分析与修复方案
你的核心问题出在React Hook规则违反和Context数据传递逻辑错误上,以下是具体问题和修复步骤:
问题1:Hook使用违反规则
你在普通函数RQKitsDB里调用了useQuery,但React Hook只能在组件顶层或以use开头的自定义Hook里调用,否则React不会执行这个Hook,自然不会发起axios请求,服务器也就收不到请求。
问题2:Context传递与使用错误
你把RQKitsDB函数放到了Context的value里,但在组件中直接尝试读取RQKitsDB.data——这相当于读取一个函数的data属性,必然得到undefined,根本没有调用这个函数去执行useQuery。
修复步骤
1. 重构kitDataContext.js
把useQuery移到Provider组件内部(组件属于Hook合法调用场景),并直接将请求结果放到Context中,同时用自定义Hook封装Context的获取逻辑:
import { useQuery } from '@tanstack/react-query' import axios from 'axios' import { createContext, useContext } from 'react'; const kitsDataContext = createContext(); // 自定义Hook,封装Context获取,确保只能在Provider内部使用 export const useKitsData = () => { const context = useContext(kitsDataContext); if (!context) { throw new Error('useKitsData必须在KitsDataProvider内部使用'); } return context; }; export const KitsDataProvider = ({children}) => { // 修正fetchKits:直接返回axios请求,或用await取出数据(推荐后者,让react-query缓存实际数据) const fetchKits = async () => { const response = await axios.get("http://localhost:5001/kitsDB"); return response.data; // 返回服务器返回的实际数据 }; // 在Provider组件顶层调用useQuery,符合Hook规则 const { isLoading, data } = useQuery("kitsDB", fetchKits); // 将加载状态和数据直接传入Context return( <kitsDataContext.Provider value={{ isLoading, data }}> {children} </kitsDataContext.Provider> ); };
2. 修改SerumRow.js使用数据
用自定义HookuseKitsData获取Context中的数据,并处理加载状态:
import "./row.css" import {Button} from 'react-bootstrap'; import AddToCart from './AddToCart.js'; import { useKitsData } from './contexts/kitsDataContext.js' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { KitsDataProvider } from './contexts/kitsDataContext.js' const queryClient = new QueryClient() function SerumRowNoProviders() { // 使用自定义Hook获取数据和加载状态 const { isLoading, data } = useKitsData(); // 处理加载中状态 if (isLoading) { return <div>加载中...</div>; } return ( <div className="small-container"> <h1>SERUM PRESETS</h1> <div className="row"> {/* 使用data渲染实际数据,注意可选链避免空值报错 */} {data?.aa?.map((kit, index) => ( <div key={index} className="col-3 text-center"> <img src={kit.image || "./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg"} alt={`套件 ${index+1}`} /> <div>{kit.name}</div> <div className="priceReact">{kit.price}</div> <AddToCart /> </div> ))} </div> <h1><button type="button" id="show-more" className="btn btn-outline-dark btn-lg">浏览全部</button></h1> </div> ); } function SerumRow() { return ( <QueryClientProvider client={queryClient}> <KitsDataProvider> <SerumRowNoProviders /> </KitsDataProvider> </QueryClientProvider> ); } export default SerumRow;
额外注意点
- CORS配置:如果前后端端口不同(前端3000,后端5001),需要在后端配置CORS允许前端域名访问,否则会出现跨域错误。
- 数据结构适配:服务器返回的是
{"aa": result},所以渲染时要通过data.aa访问数组数据。
内容的提问来源于stack exchange,提问作者poltergaz
相关产品推荐
相关产品推荐

