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

如何构建axios.get以避免‘Cannot read properties of undefined (reading '0')’错误

问题分析与解决方法

错误原因

  • 异步请求顺序错误:axios.get是异步操作,你在then回调外直接访问pkmnResponse,此时请求还未完成,pkmnResponse仍是初始的undefined,读取pkmnResponse.stats[0]自然报错。
  • setState异步特性误解:setPkmnResponse是异步更新状态的,即使在then里调用,也无法立刻拿到新的状态值,必须直接使用then回调里的response.data处理数据。
  • 第二个异步请求未正确等待:获取描述的axios请求也是异步的,你直接在后面调用setPkmnStat,此时description还未被赋值,会是空字符串。
  • isLoading逻辑颠倒:你的return逻辑是isLoading为true时显示内容,false时显示加载,但初始isLoading设为true,页面加载时直接渲染未填充数据的内容,导致显示空白和破碎图片。

解决方法

  1. 将所有依赖请求结果的代码放到axios的回调内部,或使用async/await简化异步逻辑,确保数据返回后再处理。
  2. 直接使用请求返回的response.data,而非依赖setState后的状态值。
  3. 等待两个接口请求都完成后再更新pkmnStat,用Promise.all同时发起两个请求,提升效率。
  4. 修正isLoading逻辑:初始设为true,请求完成(成功/失败)后设为false,return时判断!isLoading再显示内容,否则显示加载动画。

修正后的PkmnStats代码

import axios from 'axios';
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import loading from './loading.gif';

function PkmnStats() {
    const [isLoading, setIsLoading] = useState(true);
    const [pkmnStat, setPkmnStat] = useState({
        name:'',
        index:'',
        imageUrl:'',
        types:[],
        description:'',
        stats:{
            hp:'',
            attack:'',
            defense:'',
            speed:'',
            specialAttack:'',
            specialDefense:''       
        },
        height:'',
        weight:'',
        abilities:[]
    });

    const params = useParams()
    const index = params.index
    const name = params.name

    const pkmnUrl = `https://pokeapi.co/api/v2/pokemon/${index}`
    const pkmnSpecies = `https://pokeapi.co/api/v2/pokemon-species/${index}/`
    const imageUrl = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${index}.png`

    useEffect(() => {
        const getPkmnStats = async () => {
            try {
                // 并行发起两个请求,等待全部完成
                const [pkmnRes, speciesRes] = await Promise.all([
                    axios.get(pkmnUrl),
                    axios.get(pkmnSpecies)
                ]);

                const pkmnData = pkmnRes.data;
                const speciesData = speciesRes.data;

                // 提取基础数值
                const hp = pkmnData.stats[0].base_stat;
                const attack = pkmnData.stats[1].base_stat;
                const defense = pkmnData.stats[2].base_stat;
                const speed = pkmnData.stats[5].base_stat;
                const specialAttack = pkmnData.stats[3].base_stat;
                const specialDefense = pkmnData.stats[4].base_stat;

                // 转换单位
                const height = Math.round((pkmnData.height * 0.328084 + 0.0001) * 100) / 100;
                const weight = Math.round((pkmnData.weight * 0.220462 + 0.0001) * 100) / 100;

                // 提取类型与特性
                const types = pkmnData.types.map(type => type.type.name);
                const abilities = pkmnData.abilities.map(ability => ability.ability.name);

                // 提取英文描述
                let description = '';
                speciesData.flavor_text_entries.some(flavor => {
                    if (flavor.language.name === 'en') {
                        description = flavor.flavor_text;
                        return true;
                    }
                    return false;
                });

                // 更新状态
                setPkmnStat({
                    index,
                    name,
                    imageUrl,
                    types,
                    stats: { hp, attack, defense, speed, specialAttack, specialDefense },
                    height,
                    weight,
                    abilities,
                    description
                });
            } catch (error) {
                console.log("请求出错", error);
            } finally {
                // 无论请求成功失败,结束加载状态
                setIsLoading(false);
            }
        };

        getPkmnStats();
    }, [index, name]); // 参数变化时重新发起请求

    return (
        <>
            {!isLoading ? (
                <div className='mx-auto w-fit h-screen p-6  md:w-3/5'>
                    <div className='flex flex-col items-center justify-center md:flex-col lg:flex-row'>
                        <div className='flex flex-col items-center '>
                            <p className='text-5xl md:text-6xl capitalize'>{name}</p>
                            <img className=" w-32 h-32 md:w-64 md:h-64 " src={imageUrl} alt={name} />
                            <div className='flex flex-row '>
                                {types.map((type, idx) => (
                                    <div key={idx} className='mx-2 capitalize'>{type}</div>
                                ))}
                            </div>
                            <p>Height: {pkmnStat.height} ft.</p>
                            <p>Weight: {pkmnStat.weight} lbs.</p>
                        </div>
                        <div className='flex flex-col items-center '>
                            <p className='text-center my-5'>{pkmnStat.description} </p>
                            <p>Abilities: {pkmnStat.abilities.map(ability => (
                                <span key={ability} className='mx-1 capitalize'>{ability}</span>
                            ))}</p>
                            <div className='flex flex-col items-center mt-4 '>
                                <p> HP: {pkmnStat.stats.hp}</p>
                                <p> Attack: {pkmnStat.stats.attack}</p>
                                <p>Defense: {pkmnStat.stats.defense}</p>
                                <p>Speed: {pkmnStat.stats.speed}</p>
                                <p>Spec.Attack: {pkmnStat.stats.specialAttack}</p>
                                <p>Spec.Defense: {pkmnStat.stats.specialDefense}</p>
                            </div>
                        </div>
                    </div>
                </div>
            ) : ( <img src={loading} className="mx-auto bg-platnium" alt="loading gif"/> )}
        </> 
    );
}

export default PkmnStats

额外优化点

  • 补充了useState和useEffect的导入,原代码遗漏导致运行错误。
  • 优化了类型、特性的渲染逻辑,用循环替代手动索引判断,适配多类型宝可梦。
  • 给useEffect添加依赖项,确保路由参数变化时自动重新请求对应数据。
  • 用async/await+Promise.all简化异步代码,同时并行请求提升加载速度。

内容的提问来源于stack exchange,提问作者Brad G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:18:39