在React的useEffect中使用多个axios GET请求出现值未定义问题
解决OpenWeatherMap API串联请求的问题
你遇到的问题核心有两个:
- React的
setState是异步操作,调用setCoordinates后立刻读取coordinate状态,此时状态还没更新,自然拿不到lat和lon - OpenWeatherMap地理编码API返回的是数组(即使设置了
limit=1),你把coordinate初始化为数组,但直接用coordinate['lat']是错误的,得先取数组里的第一个元素
直接给你修正后的代码,用async/await写法更直观,也避免异步状态的问题:
const Content = ({result}) => { const languages = [result['languages']] const [weather, setWeather] = useState(null) // 天气数据不是数组,初始化为null更合适 const [coordinate, setCoordinates] = useState(null) const api_key = process.env.REACT_APP_API_KEY useEffect(() => { const fetchWeatherData = async () => { try { // 第一步:获取地理编码数据 const geoResponse = await axios.get( `http://api.openweathermap.org/geo/1.0/direct?q=${result['capital']},${result['cca2']}&limit=1&appid=${api_key}` ); // 因为返回的是数组,取第一个元素 const geoData = geoResponse.data[0]; if (!geoData) { console.error('未找到对应地理坐标'); return; } setCoordinates(geoData); // 第二步:用拿到的经纬度请求天气数据 const weatherResponse = await axios.get( `https://api.openweathermap.org/data/3.0/onecall?lat=${geoData.lat}&lon=${geoData.lon}&exclude=minutely,hourly,daily,alerts&appid=${api_key}` ); setWeather(weatherResponse.data); } catch (error) { console.error('请求出错:', error); } }; fetchWeatherData(); // 注意:这里要把result和api_key加入依赖数组,避免闭包问题 }, [result, api_key]); // 后续渲染逻辑... };
如果坚持用链式then写法,也可以直接在第一个then里使用返回的数据,不用依赖状态:
useEffect(() => { axios .get(`http://api.openweathermap.org/geo/1.0/direct?q=${result['capital']},${result['cca2']}&limit=1&appid=${api_key}`) .then(geoResponse => { const geoData = geoResponse.data[0]; if (!geoData) throw new Error('未找到地理坐标'); setCoordinates(geoData); return geoData; // 把地理数据传递给下一个then }) .then(geoData => { return axios.get( `https://api.openweathermap.org/data/3.0/onecall?lat=${geoData.lat}&lon=${geoData.lon}&exclude=minutely,hourly,daily,alerts&appid=${api_key}` ); }) .then(weatherResponse => { setWeather(weatherResponse.data); }) .catch(error => { console.error('请求失败:', error); }); }, [result, api_key]);
另外提醒几点:
- 天气API的
exclude参数值不对,你写的exclude=1会报错,换成实际要排除的参数(比如minutely,hourly)或者删掉这个参数 - 把
result和api_key加入useEffect的依赖数组,去掉eslint-disable-next-line注释,避免闭包导致的旧值问题 - 初始状态不要用空数组,天气和坐标都是对象,初始化为
null更合理
内容的提问来源于stack exchange,提问作者Dharmapala
相关产品推荐
相关产品推荐

