I am trying to access the weather information from an API call to OpenWeatherMap, but I always get a "cannot read property of undefined" error.
In my App.js file I have a CallAPI function that gets passed the users coordinates and fetches the weather data. It's then passed down to my Header component with a prop of "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>
)
In my Header.js file I am currently just trying to display the weather status.
import React from "react"
function Header(props){
return(
<div>
{/*<h1>{props.curr.weather[0].main}</h1>*/}
{console.log(props.curr.weather)}
</div>
)
}
The beginning of the json file from the API looks like this.
in "current", there is a weather property that is an array with one element which is an object, thus I would assume the correct way to access the "main" property would be "current.weather[0].main". However, I get the error "cannot read property '0' of undefined" when I try to console.log or return that. The strange part is that when I console.log "current.weather" it prints an array with an object to the console.
I've tried storing "current.weather" in a variable before accessing its 0th index and I've tried passing "currWeatherData.weather" as the prop in my App.js file, both of which I don't think change anything. I'm not really sure where to go from here, can anyone help?
EDIT: after an hour or so of console.log debugging i figured out my problem. I learned that when using hooks, useState triggers rerenders the same way this.setState did, meaning each time I set the state, it rendered my Header component. I'm guessing the API call didn't finish before rendering it, so the prop was passed as undefined. I solved this by adding an isLoading state and setting it to false after the API call,
//... code above
.then(data => {
setCurrWeatherData(data.current)
setIsLoading(false)
})
and in my return, I added a conditional statement
<div>
{!isLoading && <Header curr = {currWeatherData}/>}
</div>
I skimmed through https://medium.com/swlh/how-does-react-hooks-re-renders-a-function-component-cc9b531ae7f0 to help