Reputation: 21
I'm making a simple weather app which gets the weather from an api based on the users location.
Some times it works, sometimes it says cannot read data of undefined. Here is the link to my project - https://codesandbox.io/s/weather-app-12-i0n8i?file=/src/App.js:764-983
I think the issue is that the 'Weather' component is being rendered before it receives the location data, or that the call to the weather api is being made before it receives the location data. Though I could be wrong.
Any ideas?
I've posted this question before but none of the solutions people gave worked.
Upvotes: 0
Views: 402
Reputation: 46
Exactly, You are rendering the <Weather />
component before to have the data.
You can insert an initial state for the weather data or control the status of pending data and avoid to render your component before that, for example, using maybe a loading component.
Solution: https://codesandbox.io/s/weather-app-12-forked-bu93w?file=/src/App.js
Initial State:
const [state, setState] = React.useState({
status: 'pending',
weather: null
});
You can use Lazy initialization if your state is computationally expensive:
const [state, setState] = React.useState(() => {
// ...do something
});
Upvotes: 0
Reputation: 5054
Its happening because you are trying to render the data even when data is not coming. You need to add condition to render data only when data is available. Something like this:
import React, { useState, useEffect } from "react";
import "./styles.css";
import axios from "axios";
import Weather from "./Components/Weather";
import useGeoLocation from "./Hooks/useGeoLocation";
export default function App() {
const location = useGeoLocation();
const [weather, setWeather] = useState({});
useEffect(() => {
const lat = location.coordinates.lat;
const lng = location.coordinates.lng;
console.log(lat, lng);
axios
.get(
`https://weather-proxy.freecodecamp.rocks/api/current?lat=${lat}&lon=${lng}`
)
.then((res) => {
setWeather(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
if (!location || Object.keys(weather).length === 0) return <>Loading....</>;
return (
<div className="App">
<h1>Weather App</h1>
<h1>
Location:
{location.loaded
? JSON.stringify(location)
: "Location data not available yet."}
</h1>
{location.loaded ? <Weather data={weather} /> : <h1>Loading...</h1>}
</div>
);
}
Here is the demo: https://codesandbox.io/s/weather-app-12-forked-8lehu?file=/src/App.js:0-1382
Upvotes: 1