
本文详解如何在 react 中安全、可靠地实现“先请求列表数据获取 id,再用该 id 发起第二个 api 请求”的链式调用,避免因异步时序问题导致的 cannot read property 'id' of undefined 错误。
本文详解如何在 react 中安全、可靠地实现“先请求列表数据获取 id,再用该 id 发起第二个 api 请求”的链式调用,避免因异步时序问题导致的 cannot read property 'id' of undefined 错误。
在 React 中,当第二个 API 请求依赖第一个请求返回的数据(如电影 ID)时,直接在 useEffect 中并行调用两个异步函数会导致竞态问题:MovieDetail() 在 TrendingMovies() 完成前就执行,此时 MovieList[0] 尚未被赋值,访问 .id 自然报错。
正确的做法是建立明确的依赖关系与执行时序。以下是推荐的三种实践方式(均基于现代 React + fetch):
Orderly React SDK 钩子使用参考指南,包括 useOrderEntry、usePositionStream、useOrderbookStream、useCollateral 等。
✅ 方案一:Promise 链式调用(简洁可靠)
useEffect(() => {
const options = {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: 'Bearer YOUR_API_TOKEN'
}
};
const fetchTrendingAndDetail = async () => {
try {
// 第一步:获取热门电影列表
const listRes = await fetch(
'https://api.themoviedb.org/3/trending/movie/day?language=en-US',
options
);
if (!listRes.ok) throw new Error(`List API failed: ${listRes.status}`);
const listData = await listRes.json();
const movie = listData.results[0];
if (!movie) throw new Error('No trending movie found');
// 第二步:用获取到的 ID 请求详情(串行、强依赖)
const detailRes = await fetch(
`https://api.themoviedb.org/3/movie/${movie.id}?language=en-US`,
options
);
if (!detailRes.ok) throw new Error(`Detail API failed: ${detailRes.status}`);
const detailData = await detailRes.json();
console.log('Full movie detail:', detailData);
// ✅ 此处可安全更新状态,例如:setMovieDetail(detailData)
} catch (err) {
console.error('API chain failed:', err);
// 建议添加用户友好的错误提示(如 setError(...))
}
};
fetchTrendingAndDetail();
}, []);
? 关键点:使用 await 显式等待第一步完成后再执行第二步;全程 try/catch 统一处理网络、解析、业务逻辑异常。
✅ 方案二:分离函数 + Promise 传递(更易测试与复用)
const fetchTrendingId = () =>
fetch('https://api.themoviedb.org/3/trending/movie/day?language=en-US', options)
.then(res => {
if (!res.ok) throw new Error('Trending fetch failed');
return res.json();
})
.then(data => {
const first = data.results[0];
if (!first?.id) throw new Error('Invalid trending response: missing ID');
return first.id; // ? 只返回关键依赖值
});
const fetchMovieDetail = (id: number) =>
fetch(`https://api.themoviedb.org/3/movie/${id}?language=en-US`, options)
.then(res => {
if (!res.ok) throw new Error(`Detail fetch failed for ID ${id}`);
return res.json();
});
// 在 useEffect 中组合
useEffect(() => {
fetchTrendingId()
.then(id => fetchMovieDetail(id))
.then(detail => console.log('Success:', detail))
.catch(err => console.error('Chain error:', err));
}, []);
⚠️ 注意事项与最佳实践
- 不要在 useEffect 中混用 .then() 和顶层 await:React 官方明确不推荐在 useEffect 回调中直接 await(需包裹为 IIFE 或封装为 async 函数),否则可能触发 ESLint 警告且难以调试。
- 始终校验响应有效性:API 可能返回空数组、无 id 字段或 HTTP 错误码,务必检查 res.ok 和数据结构。
- 避免状态竞态(Race Condition):若组件卸载后异步回调才执行(如快速跳转页面),应使用 AbortController 或 mounted 标志防止 setState 在已卸载组件上调用(生产环境强烈建议)。
- 考虑加载状态与错误 UI:实际项目中应配合 useState 管理 loading、error、data 三态,提升用户体验。
通过以上任一方案,你都能确保第二个请求严格依赖第一个请求的成功结果,彻底解决 undefined.id 类型错误,并构建出健壮、可维护的数据获取流程。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










