React中useEffect内API请求函数未执行及map报错问题排查
问题分析与解决方案:API调用无输出+map读取undefined报错
问题原因
1. 控制台未打印「Hello」
组件初始化时location.state可能为undefined,执行fromStation = location.state.fromS直接抛出错误,导致组件渲染中断,useEffect中的trainDetails()完全没机会执行,因此不会打印「Hello」。此外,trainDetails未做错误捕获,若API请求抛出异常也会中断执行,但「Hello」在请求前,核心原因还是location.state的未校验问题。
2. 「Cannot read properties of undefined (reading 'map')」报错
trainData初始值设为空字符串"",API请求返回前trainData.data是undefined,直接调用map方法触发错误。- 即使请求成功,若返回数据结构不符合预期,
trainData.data仍可能为undefined,同样会报错。
解决方案
1. 校验location.state,避免初始化崩溃
读取location.state属性前先做可选链判断,或者直接在组件渲染前校验:
// 方式1:可选链+默认值 const fromStation = location.state?.fromS || ''; const toStation = location.state?.toS || ''; // 方式2:提前校验,不符合则提示 if (!location.state?.fromS || !location.state?.toS) { return <div>请选择有效的出发/到达车站</div>; }
2. 修复trainData初始值与map前的安全校验
- 将
trainData初始值改为包含空数组的对象,确保data属性始终存在:
const [trainData, setTrainData] = useState({ data: [] });
- 调用
map前用可选链判断trainData.data是否存在,同时添加唯一key属性避免React警告:
{trainData.data?.map((train) => { return ( <div className="train-container" key={train.trainNumber}> <Box> <Card train={train} /> </Box> <div className="btn"> <Button>Book</Button> </div> </div> ); })}
3. 给异步请求添加错误捕获,修正请求成功判断逻辑
原代码中!response.ok的判断逻辑错误(axios的response.ok在2xx状态码时为true),同时添加try/catch捕获请求异常:
async function trainDetails() { setLoading(true); console.log("Hello"); try { const options = { method: "GET", url: "https://irctc1.p.rapidapi.com/api/v3/trainBetweenStations", params: { fromStationCode: `${fromStation}`, toStationCode: `${toStation}`, dateOfJourney: "2023-05-20", }, headers: { "X-RapidAPI-Key": "{apiKey}", "X-RapidAPI-Host": "irctc1.p.rapidapi.com", }, }; const response = await axios.request(options); console.log(response.status); // 修正判断逻辑:2xx状态码时为请求成功 if (response.ok) { console.log(response.data.data); setTrainData(response.data); } else { console.log('请求失败,状态码:', response.status); } } catch (error) { console.error('API请求出错:', error); } finally { setLoading(false); } }
4. 完善useEffect依赖数组
如果出发/到达车站变化时需要重新请求数据,将fromStation和toStation加入依赖,同时判断有效值再执行请求:
useEffect(() => { if (fromStation && toStation) { trainDetails(); } }, [fromStation, toStation]);
内容的提问来源于stack exchange,提问作者Kshitij Verma
相关产品推荐
相关产品推荐

