You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    </>
  );
}

错误原因

  1. 初始状态缺失types属性:你初始化result为{}空对象,组件首次渲染时result.types是undefined,直接调用map方法必然报错。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:45:23