首页 > 解决方案 > OpenWeatherMap API:无法读取未定义的属性

问题描述

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

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

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文件

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

安慰

在访问第 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以提供帮助

标签: javascriptjsonreactjs

解决方案


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


推荐阅读