React天气应用:调用API时使用map遍历list出现TypeError错误求助
天气应用map访问API list报错解决方案
问题详情
开发天气应用时,调用API后使用map遍历返回的list属性,触发以下错误:
react-refresh-runtime.development.js:315 Uncaught TypeError: Cannot read properties of undefined (reading 'map')
推测原因是API请求未完成时,组件已执行渲染逻辑,此时list尚未被赋值。
组件代码
function ApiCall({ getSelection }) { const [takeData, setTakeData] = useState({}) const [loading, setLoading] = useState(false) useEffect(() => { const fetchApi = async () => { try { const res = await axios(`https://api.openweathermap.org/data/2.5/forecast?q=${getSelection}&appid="Here is the API key" `) setTakeData(res.data) console.log(res.data) } catch (err) { console.error(err) } setLoading(false) } fetchApi() }, [getSelection]) if (loading===true) { return <div>Loading...</div> } const { city, list } = takeData // console.log("IS UPDATED: ",city?.name) return ( <div> { // use map method since it is a list list.map(el => el[0].main.temp) } </div> ) }
API返回数据结构
list: Array(40) 0: clouds: {all: 0} dt: 1660726800 dt_txt: "2022-08-17 09:00:00" main: {temp: 299.42, feels_like: 299.42, temp_min: 299.42, temp_max: 301.99, pressure: 1006, …} pop: 0 sys: {pod: 'd'} visibility: 10000 weather: [{…}] wind: {speed: 2.31, deg: 292, gust: 3.03} [[Prototype]]: Object 1: {dt: 1660737600, main: {…}, weather: Array(1), clouds: {…}, wind: {…}, …} 2: {dt: 1660748400, main: {…}, weather: Array(1), clouds: {…}, wind: {…}, …}
解决步骤
1. 修正初始状态避免undefined
初始时takeData是空对象,解构出的list为undefined,直接调用map必然报错。有两种处理方式:
- 初始化
takeData时给list设空数组:const [takeData, setTakeData] = useState({ list: [] }) - 或者在
map前加可选链判断,避免执行不存在的方法:list?.map(...)
2. 修复map取值错误
从API结构可以看到,list的每个元素本身就包含main属性,不需要el[0],直接取el.main.temp即可,否则会触发新的取值错误。
3. 完善loading状态逻辑
当前loading初始为false,请求开始时未切换为true,导致第一次渲染不会显示加载提示。需要在请求开始时设置loading为true:
const fetchApi = async () => { setLoading(true) // 添加这行 try { // 原有请求逻辑 } catch (err) { console.error(err) } setLoading(false) }
4. 给列表项添加key
React列表渲染要求每个子项必须有唯一key属性,避免渲染警告。
修正后的完整代码
function ApiCall({ getSelection }) { const [takeData, setTakeData] = useState({ list: [] }) const [loading, setLoading] = useState(false) useEffect(() => { const fetchApi = async () => { setLoading(true) try { const res = await axios(`https://api.openweathermap.org/data/2.5/forecast?q=${getSelection}&appid="Here is the API key" `) setTakeData(res.data) console.log(res.data) } catch (err) { console.error(err) } setLoading(false) } fetchApi() }, [getSelection]) if (loading) { return <div>Loading...</div> } const { city, list } = takeData return ( <div> {list.map((el, index) => ( <div key={index}>{el.main.temp}</div> ))} </div> ) }
内容的提问来源于stack exchange,提问作者Recep Çankaya
相关产品推荐
相关产品推荐

