开发者问题收集

未捕获的类型错误:无法读取未定义但已定义的属性

2022-01-21
510

此应用程序的目的是对 Google Places API 进行 API 调用,收集有关餐厅的信息,然后显示给用户。

该应用程序在大多数情况下都可以正常工作,但平均每 5-10 次 API 调用一次,应用程序就会崩溃。

错误:

在此处输入图像描述

代码:

// State and global variables //

const [searchResponse, setSearchResponse] = useState("");
const [secondarySearchResponse, setsecondarySearchResponse] = useState("");
const [information, setInformation] = useState("");
const [secondaryInformation, setSecondaryInformation] = useState("");
const [itemFilter, setFilter] = useState("");
const [place_id, setPlaceId] = useState("");
const [dataReady, setDataReady] = useState(false);
const [locationHad, setLocationHad] = useState(false);
const pos = useRef(null);
const key = "AIzaSyD1ZTsmbDBBlMpmaogO_hlj93zzbDDtAoc";
var num = Math.floor(Math.random() * 20 + 1);

// Use Effects

// Gets users current location
useEffect(() => {
  navigator.geolocation.getCurrentPosition((position) => {
    pos.current = position;
    console.log("Location had. Ready for API call.");
    setLocationHad(true);
  });
}, []);

// Once we have clicked our button and made our api call, we get the place_id and save it so we can make a secondary api call using place_id
useEffect(() => {
  if (
    searchResponse !== "" &&
    searchResponse.results[num].place_id !== undefined) {
    setPlaceId(searchResponse.results[num].place_id);
    console.log("place_id set");
    } else {
    console.log("error in setting place_id");
  }
}, [searchResponse]);

// One place_id is set we make secondary api call
useEffect(() => {
  if (place_id !== "") {
    fetchSecondaryInfo();
  } else {
    console.log("no place id!");
  }
}, [place_id]);

// Now that we have made both api calls we save the relavent info into state that we will pass down to child components
useEffect(() => {
  if (searchResponse !== "") {
    console.log(searchResponse.results[num].name);
    setInformation({
      name: searchResponse.results[num].name,
      open_now: searchResponse.results[num].opening_hours.open_now,
      rating: searchResponse.results[num].rating,
      price: searchResponse.results[num].price_level,
      location: {
        lat: searchResponse.results[num].geometry.location.lat,
        lng: searchResponse.results[num].geometry.location.lng,
      },
    });
    console.log("info set!");
  } else {
    console.log("no info to set!");
  }
}, [searchResponse]);

// And again for the secondary info (I broke this dwown into to seperate useEffects trying to figure out what was causing my error...)
useEffect(() => {
  if (secondarySearchResponse !== "") {
    setSecondaryInformation({
      phone_number: secondarySearchResponse.result.formatted_phone_number,
      daily_hours: secondarySearchResponse.result.opening_hours.weekday_text,
      address: secondarySearchResponse.result.formatted_address,
    });
    setDataReady(true);
    console.log("secondary info set!");
  } else {
    console.log("no secondary info to set!");
  }
}, [secondarySearchResponse]);

// Function that makes api call
async function fetchInfo() {
  if (locationHad) {
    if (itemFilter === "") {
      var url = `https://secure-dawn-88985.herokuapp.com/https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${pos.current.coords.latitude},${pos.current.coords.longitude}&radius=12000&type=restaurant&key=${key}`;
    } else {
      var url = `https://secure-dawn-88985.herokuapp.com/https://maps.googleapis.com/maps/api/place/nearbysearch/json?keyword=${itemFilter[0]}&location=${pos.current.coords.latitude},${pos.current.coords.longitude}&radius=12000&type=restaurant&key=${key}`;
    }

    await fetch(url)
      .then((response) => response.json())
      .then((data) => setSearchResponse(data))
      .then(console.log("api request fired."));
  } else {
    console.log("location not yet identified!");
  }
}

// Function that makes secondary api call
async function fetchSecondaryInfo() {
  if (place_id !== "") {
    const secondary_url = `https://secure-dawn-88985.herokuapp.com/https://maps.googleapis.com/maps/api/place/details/json?fields=formatted_phone_number,opening_hours,formatted_address&place_id=${place_id}&key=${key}`;

    await fetch(secondary_url)
      .then((response) => response.json())
      .then((data) => setsecondarySearchResponse(data))
      .then(console.log("secondary api request fired."));
  } else {
    console.log("place_id not had in secondary fetch.");
  }
}

至于 place_id 错误,我输入了一行特定的代码来避免此错误:

 useEffect(() => {
  if (
    searchResponse !== "" &&
    searchResponse.results[num].place_id !== undefined
  ) {
    console.log(searchResponse.results[num].place_id);
    setPlaceId(searchResponse.results[num].place_id);
    console.log("place_id set");
  } else {
    console.log("error in setting place_id");
  }
}, [searchResponse]);

所以我不明白在那一行中怎么可能抛出这个错误。

至于名称错误,我输入了一行特定的代码来控制台记录对象在读取属性之前会失败,但在抛出错误之前不会在控制台中打印:

useEffect(() => {
  if (searchResponse !== "") {
    console.log(searchResponse.results[num].name);
    setInformation({
      name: searchResponse.results[num].name,
      open_now: searchResponse.results[num].opening_hours.open_now,
      rating: searchResponse.results[num].rating,
      price: searchResponse.results[num].price_level,
      location: {
        lat: searchResponse.results[num].geometry.location.lat,
        lng: searchResponse.results[num].geometry.location.lng,
      },
    });
    console.log("info set!");
    ..........

我很感激任何意见、建议、批评等。

1个回答

错误消息显示错误在 行抛出:

searchResponse.results[num].place_id !== undefined

如果 searchResponse.results[num] 不存在,则会抛出此错误。

为了简洁起见,请尝试使用可选链接(并将 searchResponse 初始化为未定义或 null)。执行

const [searchResponse, setSearchResponse] = useState();

并将

if (
    searchResponse !== "" &&
    searchResponse.results[num].place_id !== undefined) {
    setPlaceId(searchResponse.results[num].place_id);

更改为

const possiblePlaceId = searchResponse?.results[num]?.place_id;
if (possiblePlaceId) {
    setPlaceId(possiblePlaceId);
CertainPerformance
2022-01-21