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

React+TypeScript调用Rest Countries API获取嵌套数据报错求助

解决Rest Countries API中语言和货币的渲染问题

你的问题出在两个核心点:接口类型定义错误,以及嵌套数据的访问方式不对。以下是具体修正步骤:

1. 修正TypeScript接口定义

Rest Countries API返回的languages和currencies是键值对对象,不是数组;另外capital、timezones是数组,borders可能为空。更新接口:

interface Country {
  name: {
    common: string;
    official: string;
  };
  capital?: string[];
  flags: {
    svg: string;
  };
  region: string;
  languages?: { [code: string]: string };
  currencies?: { [code: string]: { name: string; symbol: string } };
  timezones: string[];
  borders?: string[];
}

2. 修正State类型

不要用any[],明确指定类型:

const [country, setCountry] = useState<Country[]>([]);

3. 正确渲染嵌套数据

针对语言、货币、时区、首都和边境,处理空值并正确访问嵌套内容:

  • 语言:用Object.values提取所有语言名称,再拼接
  • 货币:遍历货币对象,提取名称和符号后拼接
  • 其他字段:处理可能为空的情况,避免报错

完整修正后的代码

import { useParams } from "react-router-dom";
import { useState, useEffect } from "react";
import axios from "axios";

const Country = () => {
  interface Country {
    name: {
      common: string;
      official: string;
    };
    capital?: string[];
    flags: {
      svg: string;
    };
    region: string;
    languages?: { [code: string]: string };
    currencies?: { [code: string]: { name: string; symbol: string } };
    timezones: string[];
    borders?: string[];
  }

  const { id } = useParams();

  const [country, setCountry] = useState<Country[]>([]);
  const [isLoading, setLoading] = useState<boolean>(false);
  const [isError, setError] = useState<any>(null);

  useEffect(() => {
    const singleData = async () => {
      try {
        setLoading(true);
        const response = await axios.get(
          `https://restcountries.com/v3.1/name/${id}`,
        );
        setCountry(response.data);
      } catch (err) {
        console.log(err);
        setError(err);
      } finally {
        setLoading(false);
      }
    };
    singleData();
  }, [id]);

  return (
    <div className='w-full h-screen p-4 flex justify-center items-center'>
      {isLoading && <p className='text-xl font-medium'>...Loading</p>}
      {isError && (
        <p className='text-xl font-medium'>Error loading country details </p>
      )}
      {country.map((countryItem: Country, key: number) => (
        <div
          key={key}
          className='w-4/5 rounded-2xl h-2/3 flex bg-slate-900 p-4 gap-4 text-slate-200 '>
          <div className='w-4/5 flex justify-center items-center'>
            <img
              className='w-fit h-70 object-contain'
              src={countryItem.flags.svg}
              alt={`${countryItem.name.common} flag`}
            />
          </div>
          <div className='w-full h-full p-4'>
            <ul className='list-none text-xl'>
              <li> Name: {countryItem.name.common}</li>
              <li> Official Name: {countryItem.name.official}</li>
              <li> Capital: {countryItem.capital ? countryItem.capital.join(", ") : "N/A"}</li>
              <li> Region: {countryItem.region}</li>
              <li> Languages: {countryItem.languages ? Object.values(countryItem.languages).join(", ") : "N/A"}</li>
              <li> Currencies: {countryItem.currencies ? Object.values(countryItem.currencies).map(curr => `${curr.name} (${curr.symbol})`).join(", ") : "N/A"}</li>
              <li> Timezone: {countryItem.timezones.join(", ")}</li>
              <li> Border: {countryItem.borders ? countryItem.borders.join(", ") : "N/A"}</li>
            </ul>
          </div>
        </div>
      ))}
    </div>
  );
};

export default Country;

关键说明

  • 把原接口里的languages: []和currencies: []改成对象类型,匹配API返回结构
  • 渲染时用Object.values()提取对象中的值,避免直接访问不存在的name属性
  • 对所有可能为空的字段(如capital、borders)增加空值判断,防止页面报错

内容的提问来源于stack exchange,提问作者clemon ezeh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:45:37