【问题标题】:OpenWeatherMap API: cannot read property of undefinedOpenWeatherMap API:无法读取未定义的属性
【发布时间】:2020-11-06 16:36:28
【问题描述】:

我试图通过 API 调用访问 OpenWeatherMap 中的天气信息,但我总是收到“无法读取未定义的属性”错误。

在我的 App.js 文件中,我有一个 CallAPI 函数,用于传递用户坐标并获取天气数据。然后它会被传递给我的 Header 组件,其 prop 为“curr”。

const [currWeatherData, setCurrWeatherData] = useState({})

useEffect(() => {
  navigator.geolocation.getCurrentPosition(CallAPI, showError);
}, [])

//... showError function

function CallAPI(position){
  const lat = position.coords.latitude
  const long = position.coords.longitude
  fetch(/*api call*/)
    .then(response => response.json())
    .then(data => {
      setCurrWeatherData(data.current)
    })
}

return (
  <div>
    <Header curr = {currWeatherData}/>
  <div>
)

在我的 Header.js 文件中,我目前只是想显示天气状态。

import React from "react"

function Header(props){
  return(
    <div>
      {/*<h1>{props.curr.weather[0].main}</h1>*/}
      {console.log(props.curr.weather)}
    </div>
  )
}

API 中 json 文件的开头如下所示。

json file

在“current”中,有一个天气属性是一个数组,其中一个元素是一个对象,因此我假设访问“main”属性的正确方法是“current.weather[0].main ”。但是,当我尝试 console.log 或返回它时,我收到错误“无法读取未定义的属性 '0'”。奇怪的是,当我 console.log "current.weather" 时,它会在控制台上打印一个带有对象的数组。

console

我尝试在访问变量的第 0 个索引之前将“current.weather”存储在变量中,并且尝试将“currWeatherData.weather”作为我的 App.js 文件中的道具传递,我不认为这两者改变任何东西。我真的不知道从这里去哪里,有人可以帮忙吗?

编辑:经过一个小时左右的 console.log 调试后,我发现了我的问题。我了解到,当使用钩子时,useState 触发重新渲染的方式与 this.setState 相同,这意味着每次我设置状态时,它都会渲染我的 Header 组件。我猜 API 调用在渲染之前没有完成,所以 prop 以未定义的形式传递。我通过添加一个 isLoading 状态并在 API 调用后将其设置为 false 解决了这个问题,

//... code above
.then(data => {
  setCurrWeatherData(data.current)
  setIsLoading(false)
})

在我的回报中,我添加了一个条件语句

<div>
  {!isLoading && <Header curr = {currWeatherData}/>}
</div>

我浏览了https://medium.com/swlh/how-does-react-hooks-re-renders-a-function-component-cc9b531ae7f0 以提供帮助

【问题讨论】:

    标签: javascript json reactjs


    【解决方案1】:

    在您的 App.js 中,您有以下代码:

    return (
      <div>
        <Header curr = {currWeatherData}/>
      <div>
    

    但是,这并未考虑异步 API 调用。因此,currWeatherData 为 null,因为 API 调用尚未完成。

    您需要考虑生命周期,并且仅在 API 调用完成后才尝试呈现数据。 React 中有多种方法可以做到这一点,具体取决于您的整体应用/组件设计。

    有一个基于 componentDidMount 的示例 here

    【讨论】:

    • 啊,我应该包含获取该位置的代码。我目前正在使用 useEffect 调用 API useEffect(() =&gt; { navigator.geolocation.getCurrentPosition(CallAPI, showError) }, []) 我被告知这与 componentDidMount 基本相同
    • 是的,钩子是另一种方式,并且是等价的——当然,除非代码有问题!从您发布的内容中我无法判断。你知道你可以编辑你的问题以使代码完整吗?
    【解决方案2】:

    因为您使用的是功能组件。我建议您添加useEffact(()=&gt; { your api call}, [] ),这应该可以。因为目前你的代码没有得到你想要的数据!希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 2020-10-30
      • 2019-10-09
      • 1970-01-01
      相关资源
      最近更新 更多