React中TypeError: weatherData.map is not a function问题求助
解决React遍历天气API数据时的TypeError问题
问题核心原因
你碰到的TypeError: weatherData.map is not a function和console.log(weatherData.response)输出undefined,本质是三个关键错误:
- Axios响应结构误用:Axios请求返回的对象里,API实际数据存在
data字段,而非response,你把整个Axios响应对象存进了状态,这个对象不是数组,自然用不了map。 - API数据结构误解:OpenWeatherMap的
/weather接口返回的是单个天气对象,不是数组,根本不需要用map遍历。 - useEffect依赖逻辑错误:
getWeatherData函数每次组件渲染都会重新创建,导致useEffect无限重复触发请求。
分步解决方案
1. 修正数据获取逻辑
请求成功后提取response.data作为API返回的真实数据,替换原错误的状态赋值:
const getWeatherData = async () => { try { // 替换{APIKEY}为你的OpenWeatherMap密钥 const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${search}&appid={APIKEY}`); // 仅存储API返回的实际数据 setWeatherData(response.data); } catch (err) { console.error(err); } }
2. 调整状态与渲染逻辑
因为返回的是单个对象,初始状态设为null,渲染时先判断数据是否存在,再直接读取属性(注意国家信息在sys.country字段):
// 初始状态设为null,而非数组 const [weatherData, setWeatherData] = useState(null); // 替换原map渲染逻辑 {weatherData && ( <div> <h1>{weatherData.name}, {weatherData.sys.country}</h1> </div> )}
3. 修复useEffect触发问题
用useCallback包裹getWeatherData避免重复创建函数,同时添加搜索按钮,防止输入时频繁请求API:
import { useEffect, useState, useCallback } from 'react' // 用useCallback包裹,依赖search变量 const getWeatherData = useCallback(async () => { try { const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${search}&appid={APIKEY}`); setWeatherData(response.data); } catch (err) { console.error(err); } }, [search]) // useEffect仅在getWeatherData变化时触发 useEffect(() => { getWeatherData() }, [getWeatherData]) // 添加搜索按钮触发请求 const handleSearch = () => { getWeatherData() } // 输入框绑定value,避免状态不一致 <div className='inputContainer'> <input className='searchInput' type="text" onChange={handleChange} value={search} /> <button onClick={handleSearch}>搜索天气</button> </div>
修改后的完整代码
import axios from 'axios' import { useEffect, useState, useCallback } from 'react' import './App.css' function App() { const [search, setSearch] = useState("london") const [weatherData, setWeatherData] = useState(null) const getWeatherData = useCallback(async () => { try { // 替换{APIKEY}为你的真实密钥 const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${search}&appid={APIKEY}`); setWeatherData(response.data); } catch (err) { console.error(err); } }, [search]) useEffect(() => { getWeatherData() }, [getWeatherData]) const handleChange = (e) => { setSearch(e.target.value) } const handleSearch = () => { getWeatherData() } return ( <div className="App"> <div className='inputContainer'> <input className='searchInput' type="text" onChange={handleChange} value={search} /> <button onClick={handleSearch}>搜索天气</button> </div> {weatherData && ( <div> <h1>{weatherData.name}, {weatherData.sys.country}</h1> <p>当前温度:{(weatherData.main.temp - 273.15).toFixed(1)}°C</p> </div> )} </div> ) } export default App
内容的提问来源于stack exchange,提问作者mohdh34m
相关产品推荐
相关产品推荐

