Dreamer96
Dreamer96

Reputation: 11

Cannot read property "temp" of undefined

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

Answers (2)

PR7
PR7

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

DecPK
DecPK

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

Codesandbox

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

Related Questions