开发者问题收集

在 useEffect 中设置状态然后访问其属性

2020-07-21
553

我尝试访问我的状态下使用 React 中的 useEffect 钩子设置的属性,但我一直收到此错误 Uncaught “TypeError:无法读取未定义的属性‘0’” 。 这是我的代码:-

import React, { useState, useEffect } from "react";

const Geocode = (props) => {
  const [location, setLocation] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(
        `https://eu1.locationiq.com/v1/search.php?key=MY_KEY=${props.address}&format=json&limit=1`
      );
      const data = await response.json();
      setLocation((location) => ({ ...location, data }));
    }
    fetchData();
  }, [props.address]);

  const latitude = location.data[0].lat;
  const longitude = location.data[0].lon;

  return (
    <div>
      <h2>Location</h2>
      {location && (
        <p>
          Lat: {latitude}, Lon: {longitude}
        </p>
      )}
    </div>
  );
};

export default Geocode;

以下 API 调用的输出是:-

[{…}]
0:
boundingbox: (4) ["-1.444471", "-1.163332", "36.6509378", "37.1038871"]
class: "place"
display_name: "Nairobi, Kenya"
icon: "https://locationiq.org/static/images/mapicons/poi_place_city.p.20.png"
importance: 0.73502675943376
lat: "-1.2832533"
licence: "https://locationiq.com/attribution"
lon: "36.8172449"
osm_id: "9185096"
osm_type: "relation"
place_id: "237011109"
type: "city"
__proto__: Object
length: 1
__proto__: Array(0)
2个回答

useEffect 在组件在 dom 中呈现后执行。因此,当初始加载组件时,它会获取 location 默认值作为 [] 。因此,当它访问 data 属性时,它会变得未定义并引发错误。解决此问题的最佳方法是检查 location 是否具有 data 属性。您可以通过两种方式做到这一点:

1.可选链接

  const latitude = location?.data?.[0]?.lat;
  const longitude = location?.data?.[0]?.lon;

您可以在此处阅读有关它的更多信息 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

2. 条件检查

 const latitude = location.data && location.data.length > 0 ?location.data.[0].lat: 0;
 const longitude = location.data && location.data.length > 0 ? location.data.[0].lon : 0;

此外,我建议将默认值分配给 location 作为空对象 {},因为您为其分配了一个对象而不是数组。这将使代码更不容易出错。

Pranay Tripathi
2020-07-22

该行

  const latitude = location.data[0].lat;

正在抛出错误,因为在 useEffect 有机会获取和填充数据之前,您正在尝试访问它。

您正在使用 {location && (...) 在 JSX 中防止该错误,因此无需在外部定义纬度和经度,只需将计算结果放在其中即可。

此外,您应该标准化 location 状态的类型?首次定义它时,您将默认值设置为列表 [] ,但是当您更新它时,您会创建一个对象 {

Luke Storry
2020-07-22