Reputation: 37
I continue to struggle with what I believe would be something simple to accomplish. The first time I tried this I used React Hooks, but this time I switched back to class based components just because I thought it would change something for some reason.
import React, { Component } from 'react'
import Search from './components/layout/Search'
import axios from 'axios'
class App extends Component {
state = {
weather: {},
loading: false
}
sendUp = async (state) => {
this.setState({loading: true});
const res = await axios.get(`http://api.openweathermap.org/data/2.5/weather?q=${state}&appid={api key hidden for post.}`)
this.setState({weather: res.data})
this.setState({loading: false})
}
render() {
return (
<React.Fragment>
<div className="container">
<Search sendUp={this.sendUp} />
<h1>Testing this stuff {this.state.weather.coord.lat} </h1>
</div>
</React.Fragment>
)
}
}
export default App
Hopefully my confusion makes sense. I thought it would be as simple as pulling the date like this: {this.state.weather.coord.lat}. However, I get this error. Cannot read property 'lat' of undefined. Did I just miss some sort of basic javascript fundamental or is calling nested objects different when using the React Library?
{
"weather": {
"coord": "{lat: 32.88, lon: -111.76}",
"weather": "[{…}]",
"base": "stations",
"main": "{feels_like: 311.12, humidity: 32, pressure: 1012, …}",
"visibility": 10000,
"wind": "{deg: 330, speed: 3.6}",
"clouds": "{all: 1}",
"dt": 1595714117,
"sys": "{country: \"US\", id: 3616, sunrise: 1595680572, suns…}",
"timezone": -25200,
"id": 5288636,
"name": "Casa Grande",
"cod": 200
},
"loading": false
}
Upvotes: 0
Views: 197
Reputation: 11156
Ciao, you got undefined because this.state.weather
contains an element called weather
so if you want to access to your object you have to write this.state.weather.weather
. But there is another problem: if you want to get lat
from coord
you cannot write this.state.weather.weather.coord.lat
because this.state.weather.weather.coord
is a string, not a JSON object. And you cannot do neither something like JSON.parse(this.state.weather.weather.coord)
because is not a valid JSON. So, we have to work with string and, finally, to get lat
from coord
you can do:
this.state.weather.weather.coord.split(',')[0].split(':')[1]
Upvotes: 2
Reputation: 12672
the render
function is executed at the very beginning of your component being mounted.
Everytime your state changes, the render
function will be executed again. There are other situations where the component might render (for example, props changing).
The first time your component renders, your state is
state = {
weather: {},
loading: false
}
but in your render
function, you do
<h1>Testing this stuff {this.state.weather.coord.lat} </h1>
This is because at this point, you haven't loaded the weather
info yet. Your render
component should consider that. For instance, you could do something like
{ this.state.weather.coord ? <h1>Testing this stuff {this.state.weather.coord.lat}</h1> : <h1>Loading weather data...</h1>}
That way, until your weather data is loaded, you see the text "Loading...". You could also do something more sophisticated, like showing a spinner.
Upvotes: 1