Reputation: 11
it's my first time here. I'm just starting to learn React and I'm having a little problem creating a weather app. When I try to recall the temp value I get the message: cannot read property "temp" of undefined. I would be very grateful for a hint if someone sees an error. I'm attaching the code
import React, { useState } from "react";
import axios from "axios";
export default function Weather() {
let [city, setCity] = useState("");
let [weather, setWeather] = useState("");
function showWeather(response) {
setWeather(response.data);
}
function handleChange(event) {
setCity(event.target.value);
}
function displayTemperature(event) {
event.preventDefault();
let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=97a9745b0c3a1f932357060a2331ab49&units=metric`;
axios.get(url).then(showWeather);
}
let form = (
<div>
<form onSubmit={displayTemperature}>
<input type="text" onChange={handleChange} />
<input type="submit" value="Search" />
</form>
</div>
);
return (
<div>
{form}
<ul>
<li>Temperature: {weather.main.temp}°C</li>
<li>Description: {weather.weather[0].description}</li>
<li>Humidity: {weather.main.humidity}%</li>
<li>Wind: {weather.wind.speed}km/h</li>
<li>
<img
src={`http://openweathermap.org/img/wn/${weather.weather[0].icon}@2x.png`}
alt=""></img>
</li>
</ul>
</div>
);
}
Upvotes: 1
Views: 2596
Reputation: 1914
It is showing the error because in the beginning the value of weather
is empty string and you are trying to access the property main.temp
from it.
You can solve this by using conditional rendering by showing the list
only when weather
is not empty.
Also not related to this issue but you should add a catch method in displayTemperature
method while fetching the data for error handling.
Here is an example below :
import React, { useState } from "react";
import axios from "axios";
export default function Weather() {
let [city, setCity] = useState("");
let [weather, setWeather] = useState("");
function showWeather(response) {
setWeather(response.data);
}
function handleChange(event) {
setCity(event.target.value);
}
function displayTemperature(event) {
event.preventDefault();
let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=97a9745b0c3a1f932357060a2331ab49&units=metric`;
axios.get(url)
.then(showWeather)
.catch(err => console.log(err));
}
let form = (
<div>
<form onSubmit={displayTemperature}>
<input type="text" onChange={handleChange} />
<input type="submit" value="Search" />
</form>
</div>
);
return (
<div>
{form}
{/* Conditionally rendering the list */}
{weather && (
<ul>
<li>Temperature: {weather.main.temp}°C</li>
<li>Description: {weather.weather[0].description}</li>
<li>Humidity: {weather.main.humidity}%</li>
<li>Wind: {weather.wind.speed}km/h</li>
<li>
<img
src={`http://openweathermap.org/img/wn/${weather.weather[0].icon}@2x.png`}
alt=""></img>
</li>
</ul>
)}
</div>
);
}
Upvotes: 1
Reputation: 25408
In the initial state weather
is an empty string so before the API hit all the value that you're accessing from weather
will be not available so you could use either optional chaining
weather?.main?.humidity
or && operator
weather && Array.isArray(weather) && weather[0].description
import React, { useState } from "react";
import axios from "axios";
export default function Weather() {
let [city, setCity] = useState("");
let [weather, setWeather] = useState("");
function showWeather(response) {
setWeather(response.data);
}
function handleChange(event) {
setCity(event.target.value);
}
function displayTemperature(event) {
event.preventDefault();
let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=97a9745b0c3a1f932357060a2331ab49&units=metric`;
console.log(url);
axios.get(url).then(showWeather);
}
function getImageIcon(weather) {
const value = weather && Array.isArray(weather) && weather[0].icon;
return value;
}
let form = (
<div>
<form onSubmit={displayTemperature}>
<input type="text" onChange={handleChange} />
<input type="submit" value="Search" />
</form>
</div>
);
return (
<div>
{form}
<ul>
<li>Temperature: {weather?.main?.temp}°C</li>
{weather && Array.isArray(weather) && weather[0]?.description}
<li>
Description:{" "}
{weather && Array.isArray(weather) && weather[0].description}
</li>
<li>Humidity: {weather?.main?.humidity}%</li>
<li>Wind: {weather?.wind?.speed}km/h</li>
<li>
<img
src={`http://openweathermap.org/img/wn/${getImageIcon()}@2x.png`}
alt=""
></img>
</li>
</ul>
</div>
);
}
Upvotes: 2