【问题标题】:How to map through api data in React?如何在 React 中映射 api 数据?
【发布时间】:2020-01-25 07:01:05
【问题描述】:

我正在使用国家/地区 API 构建一个应用程序,该应用程序显示一个国家/地区的名称、人口和地区等信息。 我想显示该国的语言、货币和边界。 我试图映射数据以显示边界,但它说地图未定义。

<div>
    // this works and displays
    <h1>{info.name}</h1>
    <p>Population: {info.population}</p>
    <p>Region: {info.region}</p>
    <p>Capital: {info.capital}</p>
    <h4>Languages:</h4> 
    // this gives the error 'cannot map of undefined'
    <ul>
        {info.borders.map((border) => {
          return <li key={border.name}>{border.name}</li>; })}
    </ul>
</div>

这是我正在使用的响应数据

data:
name: "Brazil"
topLevelDomain: [".br"]
alpha2Code: "BR"
alpha3Code: "BRA"
callingCodes: ["55"]
capital: "Brasília"
altSpellings: (4) ["BR", "Brasil", "Federative Republic of Brazil", "República Federativa do Brasil"]
region: "Americas"
subregion: "South America"
population: 206135893
latlng: (2) [-10, -55]
demonym: "Brazilian"
area: 8515767
gini: 54.7
timezones: (4) ["UTC-05:00", "UTC-04:00", "UTC-03:00", "UTC-02:00"]
borders: (10) ["ARG", "BOL", "COL", "GUF", "GUY", "PRY", "PER", "SUR", "URY", "VEN"]
nativeName: "Brasil"
numericCode: "076"
currencies: [{…}]
languages: [{…}]

以下是我获取数据的方式

const Infopage = () => {
  const [info, setInfo] = useState({});

  const code = useParams().alpha3Code;

  useEffect(() => {
    console.log('info');
    axios
      .get(`https://restcountries.eu/rest/v2/alpha/${code}`)
      .then((response) => {
        console.log(response);
        setInfo(response.data);
      });

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div>
      <CountryInfo info={info} />
    </div>
  );
};
export default Infopage;

我也试过这个问题

 const [info, setInfo] = useState({});
  const [isLoading, setIsLoading] = useState(false);

  const code = useParams().alpha3Code;

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);
      const result = await axios.get(
        `https://restcountries.eu/rest/v2/alpha/${code}`
      );
      setInfo(result.data);
      setIsLoading(false);
    };
    fetchData();
  }, [code]);

  return (
    <div>{isLoading ? <h1>Loading...</h1> : <CountryInfo info={info} />}</div>

【问题讨论】:

  • 仅供参考,为了清楚起见,这并不是说map 未定义,而是说您的borders 属性未定义,因此它无法访问map 函数。

标签: javascript reactjs


【解决方案1】:

根据您的问题很难判断,但我敢打赌info 是一个空对象,JavaScript 为您提供每个属性访问的undefined。因为其他属性按原样使用,所以不会引发异常,但是因为您尝试调用.borders 上的方法,所以该行会引发异常。

如果是这种情况,可能是因为您使用const [info, setInfo] = useState({}) 并依赖useEffect 来填充对象。这意味着在第一次渲染(至少)直到useEffect 中的任何异步工作解决之前,useState 返回初始值。如果是这种情况,您应该在填充之前显示加载状态(或无数据)。请记住,React 可能会出于任何原因多次渲染您的组件,因此不要依赖渲染计数或排序。

如果可能,请添加有关如何获取数据的详细信息。如果没有,请在尝试构建 React 元素(&lt;div&gt;)之前添加一个断点(或 console.log)。

【讨论】:

  • 我已编辑以显示我如何获取数据。我明白你所说的关于加载状态的内容并试图实现它。但是我无法让它工作或理解如何。是否将loading设置为true,然后将数据取回为false?
【解决方案2】:

选项 1:解构并为边框分配默认值。

const { borders = [] } =  info;

// use `borders` directly
  <ul>
    {borders.map((border) => {
      return <li key={border.name}>{border.name}</li>;
    })}
  </ul>

选项 2:检查未定义/空值

  <ul>
    {info && info.borders && info.borders.length > 0 && info.borders.map((border) => {
      return <li key={border.name}>{border.name}</li>;
    })}
  </ul>

【讨论】:

  • 我已经编辑了上面的代码以显示我的信息状态以及我如何接收数据。您的建议是否仍适用于更新?
  • 这已经奏效,现在我可以显示边框了。但是,您能帮我理解为什么我必须这样做吗?我想学习。
  • @DGB,很高兴听到它的工作。当第一次加载组件时,您在做 2 件事 1) 请求加载信息和 2) 渲染组件(在此期间信息为空不知道边界,因此要保护这一点,您需要添加条件渲染或默认值/数组。现在经过一段时间(毫秒或秒),您将收到来自 API 的响应,然后重新渲染发生(在此期间您有有效数据,因此它按您的预期渲染)。您还需要采取当 API 响应错误或为空时要小心,即使是这样,您也需要进行与上述相同的检查。
猜你喜欢
  • 2023-01-15
  • 2021-03-25
  • 2022-12-29
  • 1970-01-01
  • 2019-02-07
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
相关资源
最近更新 更多