React中使用useEffect调用两个存在依赖关系的API失败如何解决?
错误原因排查
- 状态初始值类型错误:
randomid初始值被设置为数组[],实际存储的是对象类型的接口返回数据,首次渲染时第二个useEffect触发,此时randomid.id为undefined,拼接进请求URL会生成非法请求路径。 - 缺少请求前置校验:第二个useEffect没有判断
randomid是否存在有效id就直接发起请求,会触发无效调用。 - 数据类型不匹配风险:第一个接口请求的是
trending/all/day,返回结果包含电影、剧集两类内容,直接拼接进/movie/路径请求时,如果拿到的是剧集类数据会返回404错误。 - 缺失错误处理逻辑:两个axios请求都没有catch捕获异常,接口报错时容易导致页面崩溃。
- 状态声明缺失:代码中未声明
key对应的状态,直接调用setkey会抛出未定义错误。
优化实现方案
方案1:保留双useEffect逻辑的修复版本
import { useState, useEffect } from 'react' import axios from 'axios' const YourComponent = () => { // 初始值设为null标记未加载状态 const [randomid, setRandomId] = useState(null) const [key, setKey] = useState(null) const API_KEY = '替换为你的实际api_key' // 获取趋势列表 useEffect(() => { axios.get(`https://api.themoviedb.org/3/trending/all/day?api_key=${API_KEY}`) .then((response) => { // 过滤仅保留电影类型,避免后续接口报错 const movieList = response.data.results.filter(item => item.media_type === 'movie') if (movieList.length) { setRandomId(movieList[0]) } }) .catch(err => console.error('获取趋势列表失败:', err)) }, [API_KEY]) // 拿到id后请求视频数据 useEffect(() => { // 无有效id时直接返回,不发起请求 if (!randomid?.id) return axios.get(`https://api.themoviedb.org/3/movie/${randomid.id}/videos?api_key=${API_KEY}&language=en-US`) .then((response) => { if (response.data.results.length) { setKey(response.data.results[0]) } }) .catch(err => console.error('获取视频数据失败:', err)) }, [randomid, API_KEY]) return <div>组件渲染逻辑</div> }
方案2:更推荐的单useEffect链式调用版本(减少冗余依赖)
import { useState, useEffect } from 'react' import axios from 'axios' const YourComponent = () => { const [key, setKey] = useState(null) const API_KEY = '替换为你的实际api_key' useEffect(() => { const fetchData = async () => { try { // 第一步:获取趋势列表 const trendRes = await axios.get(`https://api.themoviedb.org/3/trending/all/day?api_key=${API_KEY}`) const movieList = trendRes.data.results.filter(item => item.media_type === 'movie') if (!movieList.length) return // 第二步:直接用返回的id请求视频数据,无需额外存id状态 const videoRes = await axios.get(`https://api.themoviedb.org/3/movie/${movieList[0].id}/videos?api_key=${API_KEY}&language=en-US`) if (videoRes.data.results.length) { setKey(videoRes.data.results[0]) } } catch (err) { console.error('请求失败:', err) } } fetchData() }, [API_KEY]) return <div>组件渲染逻辑</div> }
内容的提问来源于stack exchange,提问作者Ayomikun
相关产品推荐
相关产品推荐

