I'm building a really basic weather app with React hooks, codesandbox.io and OpenWeatherAPI.
It's breaking at const temp = forecast.main.temp;
and returning "TypeError: Cannot read properties of undefined (reading 'temp')" It actually does run when I initially write it but breaks if I add another variable or have to edit the temp variable in any way.
import React, { useState } from "react";
import "../styles.css";
import CityCard from "./cityCard";
export default function GetWeather() {
const [city, setCity] = useState('');
const [forecast, setForecast] = useState([]);
const getCity = async (e) => {
e.preventDefault();
//API variables
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${APIkey}`;
//fetch response
try {
const res = await fetch(url);
const data = await res.json();
setForecast(data);
} catch (err) {
console.error(err);
}
};
return (
//basic input form to search by city
<div>
<h1 className="title">Weather App</h1>
<CityCard forecast={forecast} />
<form className="form" onSubmit={getCity}>
<label className="label" htmlFor="city">
<p>Search by City</p>
</label>
<input
className="input"
type="text"
name="query place"
placeholder="i.e. Seattle"
value={city} onChange={(e) => setCity(e.target.value)}
>
</input>
<button
className="button"
type="submit"
>Search</button>
</form>
</div>
);
}
CityCard
import React from "react";
import "../../src/styles.css";
export default function CityCard({ forecast }) {
//pass props to cards
const cityName = forecast.name;
const temp = forecast.main.temp;
return (
<div className="card-container">
<p className="card-title">{cityName}</p>
<p>Temp: {temp} </p>
</div>
);
}
CodePudding user response:
Issue
The initial forecast
state is declared as an array:
const [forecast, setForecast] = useState([]);
and passed to CityCard
on forecast
prop:
<CityCard forecast={forecast} />
then accessed as if it were an object:
function CityCard({ forecast }) {
//pass props to cards
const cityName = forecast.name; // OK, undefined
const temp = forecast.main.temp; // Not OK, can't access temp of undefined
return (
<div className="card-container">
<p className="card-title">{cityName}</p>
<p>Temp: {temp}</p>
</div>
);
}
Solution
Use Optional Chaining operator to protect against null/undefined property accesses.
function CityCard({ forecast }) {
//pass props to cards
const cityName = forecast?.name;
const temp = forecast?.main?.temp;
return (
<div className="card-container">
<p className="card-title">{cityName}</p>
<p>Temp: {temp}</p>
</div>
);
}
Or wait to render CityCard
when there's a valid forecast
data to display.
const [forecast, setForecast] = useState();
...
{forecast?.name && forecast?.main?.temp && <CityCard forecast={forecast} />}