React项目中使用map处理Pokemon API的types数组报错排查
问题:React渲染宝可梦类型时map方法报错
我是新手,正在开发宝可梦维基页面,用axios获取Pokemon API的JSON数据,想渲染宝可梦类型,但对返回对象的types数组使用map时出现错误:Pokemon.jsx:30 Uncaught TypeError: Cannot read properties of undefined (reading 'map'),怀疑是JSON对象访问方式有问题,相关代码如下:
import React from "react"; import axios from "axios"; import "../styles/pokemon.css"; export default function Pokemon() { const [inputPokemon, setInputPokemon] = React.useState(""); const [result, setResult] = React.useState({}); function handleKeyDown(e) { if (e.key == "Enter") { fetchPokemon(); setInputPokemon(""); } } async function fetchPokemon() { try { const response = await axios.get( `https://pokeapi.co/api/v2/pokemon/${inputPokemon.toLowerCase()}` ); setResult(response.data); // console.log(response.data); console.log(result); } catch (error) { console.error(error); } } const typesItem = result.types.map((item) => <p>{item.type.name}</p>); return ( <> <div className="pokemon-input-container"> <h3>Search for Details about your Favorite Pokemon!</h3> <br></br> <input className="pokemon-input" type="text" placeholder="Input Pokemon Name" onChange={(e) => setInputPokemon(e.target.value)} onKeyDown={handleKeyDown} value={inputPokemon} /> </div> <div className="pokemon-output-container"> <div className="name">Name: {result.name}</div> <div className="type">Type: {typesItem}</div> <div className="weight"> Weight: {result.weight} Height: {result.height}" </div> <div className="moves">Possible Moves: </div> <div className="stats">Stats:</div> <div className="abilities">Abilities: </div> </div> </> ); }
错误原因
- 初始状态缺失types属性:你初始化
result为{}空对象,组件首次渲染时result.types是undefined,直接调用map方法必然报错。 - setState异步特性:调用
setResult(response.data)后,result不会立刻更新,所以你在fetchPokemon里打印result还是初始空对象,但这不是本次报错的直接原因。
解决方案
关键修改点
- 给初始状态的
result添加types空数组,确保首次渲染时能安全调用map - 使用可选链操作符
?.做安全访问,避免undefined报错 - 给React列表项添加唯一
key属性,消除控制台警告
修改后的代码
import React from "react"; import axios from "axios"; import "../styles/pokemon.css"; export default function Pokemon() { const [inputPokemon, setInputPokemon] = React.useState(""); // 初始化时给types设为空数组,避免首次渲染报错 const [result, setResult] = React.useState({ types: [] }); function handleKeyDown(e) { if (e.key === "Enter") { fetchPokemon(); setInputPokemon(""); } } async function fetchPokemon() { try { const response = await axios.get( `https://pokeapi.co/api/v2/pokemon/${inputPokemon.toLowerCase()}` ); setResult(response.data); } catch (error) { console.error(error); // 请求失败时重置result,避免残留旧数据 setResult({ types: [] }); } } // 可选链+空值合并,双重保险避免报错 const typesItem = result.types?.map((item) => ( <p key={item.type.name}>{item.type.name}</p> )) || []; return ( <> <div className="pokemon-input-container"> <h3>搜索你喜爱的宝可梦详情!</h3> <br /> <input className="pokemon-input" type="text" placeholder="输入宝可梦名称" onChange={(e) => setInputPokemon(e.target.value)} onKeyDown={handleKeyDown} value={inputPokemon} /> </div> <div className="pokemon-output-container"> <div className="name">名称: {result.name}</div> <div className="type">属性: {typesItem}</div> <div className="weight"> 体重: {result.weight} 身高: {result.height}" </div> <div className="moves">可用招式: </div> <div className="stats">基础数值:</div> <div className="abilities">特性: </div> </div> </> ); }
内容的提问来源于stack exchange,提问作者LearningCoder
相关产品推荐
相关产品推荐

