skip to Main Content

I am trying to create a weather app, I am currently stuck on the search bar. I’m working within a component named Inputs.tsx (stores my search bar and buttons to display different temps (F and C)

I was able to display the current location for the weather (right now it is London) but once I hit backspace in the div I immediately get the following error:

Compiled with problems:
×
ERROR
Cannot read properties of undefined (reading ‘name’)
TypeError: Cannot read properties of undefined (reading ‘name’)

I am aware that the value is set to the current default location, but how do I change that once I type another city in and how can I make it display within my App component?

Inputs.tsx

import React, { useEffect, useState } from "react";
import { GrLocation } from "react-icons/gr";
import { AiOutlineSearch } from "react-icons/ai";

function Inputs() {
  const [weather, setWeather] = useState<any>();

  useEffect(() => {
    async function load() {
      const weatherData = await getWeather();
      setWeather(weatherData);
      console.log(weatherData);
    }

    load();
  }, []);
  if (!weather) {
    return <p>loading</p>;
  }

  const handleSearch = () => {
    if (weather !== "") setWeather({ q: weather });
  };
  return (
    <div>
      <div id="search-container">
        <AiOutlineSearch onClick={handleSearch} />
        <input
          id="search-bar"
          type="text"
          placeholder="Search.."
          value={weather.location.name}
          onChange={(e) => setWeather(e.currentTarget.value)}
        ></input>
        <GrLocation />
        <div className="temperature">
          <button name="metric" id="fahrenheit-button">
            &deg;F
          </button>
          <p>|</p>
          <button name="imperial" id="celcius-button">
            &deg;C
          </button>
        </div>
      </div>
    </div>
  );
}

async function getWeather() {
  const response = await fetch(
    "https://api.weatherapi.com/v1/current.json?key=462eaa5d277d46b0957222907232503&q=London&aqi=no"
  );

  return response.json();
}

export default Inputs;

App.tsx

import { useEffect, useState } from "react";
import { ReactComponent as Logo } from "../src/mag-glass.svg";
import "./App.css";

import Inputs from "./components/Inputs";
import TemperatureAndDetails from "./components/TemperatureAndDetails";
import TimeAndLocation from "./components/TimeAndLocation";

function App() {
  const [weather, setWeather] = useState<any>();



  useEffect(() => {
    async function load() {
      const weatherData = await getWeather();
      setWeather(weatherData);
      console.log(weatherData);
    }

    load();
  }, []);
  if (!weather) {
    return <p>loading</p>;
  }
  return (
    <div className="App">
      <header className="App-header"></header>
      <Inputs />
      <TimeAndLocation />
      <h1>Weather in {weather.location.name}</h1>
      <h1 id="temp-display">{weather.current.temp_f}&deg;F</h1>
      <TemperatureAndDetails />
      <h1>Feels Like: {weather.current.feelslike_f}&deg;F</h1>
      <h1>Humidity: {weather.current.humidity}%</h1>
      <h1>Wind Speed: {weather.current.gust_mph} mph</h1>
    </div>
  );
}

async function getWeather() {
  const response = await fetch(
    "https://api.weatherapi.com/v1/current.json?key=462eaa5d277d46b0957222907232503&q=London&aqi=no"
  );

  return response.json();
}

export default App;

2

Answers


  1. Use optional chaining (?.) to handle the case when weather.location is undefined:

    value={weather?.location?.name}
    

    This will fix the issue for Inputs.

    Initialize the weather state with an empty object instead of undefined:

    const [weather, setWeather] = useState<any>({});
    

    In both cases, you should also update the handleSearch() function to properly set the weather state with the search query, instead of trying to set it directly to an object with a q property:

    const handleSearch = () => {
      if (weather.location.name !== '') {
        setWeather({ location: { name: weather.location.name } });
      }
    };
    
    Login or Signup to reply.
  2. Just use ternary operator where you drill into weather to deal with situation when weather is null:
    {weather ? weather.location.name : ”}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search