I am slowly learning JS & React, and trying to build an app that pulls weather data from various locations and displays it on a Monday.com dashboard. Still a very long way to go, but putting the puzzle pieces together 1 by 1.
I have a working app that gets the weather based on lattitude & longitude, and then displays it on the page.
Here is my code for App.js
import './App.css';
import React, { useEffect, useState } from "react";
import { Dimmer, Loader } from 'semantic-ui-react';
import Weather from './components/weather';
export default function App() {
const [lat, setLat] = useState([]);
const [long, setLong] = useState([]);
const [data, setData] = useState([]);
// this useEffect will only fire when the component mounts (once)
useEffect(() => {
navigator.geolocation.getCurrentPosition(location => {
setLat(location.coords.latitude);
setLong(location.coords.longitude);
});
}, [])
// this useEffect will be called once the component mounts when any dependency changes (lat/long)
useEffect(() => {
fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${lat}&lon=${long}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
.then(res => res.json())
.then(result_geo => {
setData(result_geo)
console.log("Latitude is:", lat) // (GL)
console.log("Longitude is:", long) // (GL)
console.log(result_geo);
});
}, [lat, long])
return (
<div className="App">
{(typeof data.main != 'undefined') ? (
<Weather weatherData={data}/>
): (
<div>
<Dimmer active>
<Loader>Loading..</Loader>
</Dimmer>
</div>
)}
</div>
);
}
And here is my code for weather.js
import React from 'react';
import '../styles.css';
import { Card } from 'semantic-ui-react'
import moment from 'moment';
const CardExampleCard1 = ({weatherData}) => (
<div className="Cards">
<Card className="card1">
<Card.Content>
<Card.Header className="header">Location: {weatherData.name}</Card.Header>
<p>{moment().format('dddd')}, {moment().format('LL')} {moment().format('HH:mm')}</p>
<br></br>
<p>Temperature: {weatherData.main.temp} °C</p>
<p>Sunrise: {new Date(weatherData.sys.sunrise * 1000).toLocaleTimeString('en-IN')}</p>
<p>Sunset: {new Date(weatherData.sys.sunset * 1000).toLocaleTimeString('en-IN')}</p>
<p>Description: {weatherData.weather[0].main}</p>
<p>Humidity: {weatherData.main.humidity} %</p>
<br></br>
</Card.Content>
</Card>
</div>
)
export default CardExampleCard1;
The next thing I am trying to figure out is how to display multiple cards (using { Card } from 'semantic-ui-react' ) for various different locations.
I am able to retrieve the weather for an additional location by duplicating the API call and changing the lat&lon (probably there's a better way), and I can store that into a variable, but I don't know how to pass that to weather.js in my return function. I have tried multiple things but it fails. And also how to update my weather.js code to then display different cards.
ANy help would be appreciated - I've been stuck on this for hours.
Eventually, I need to read location names from a monday.com board, do an API call to retrieve their geolocations, then API calls to get their weather, and then display the weather. And this can be for a variable number of locations.
CodePudding user response:
You can use the map function on an array like this below. Assuming the data in state is an array, and the response from server is a JSON object, then when calling for the second time, your array is updating by adding new object in it.
<div>
{data.map(item => <Weather weatherData={item}/>)}
</div>
import './App.css';
import React, { useEffect, useState } from "react";
import { Dimmer, Loader } from 'semantic-ui-react';
import Weather from './components/weather';
export default function App() {
const [lat, setLat] = useState([]);
const [long, setLong] = useState([]);
const [data, setData] = useState([]);
// this useEffect will only fire when the component mounts (once)
useEffect(() => {
navigator.geolocation.getCurrentPosition(location => {
setLat(location.coords.latitude);
setLong(location.coords.longitude);
});
}, [])
// this useEffect will be called once the component mounts when any dependency changes (lat/long)
useEffect(() => {
fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${lat}&lon=${long}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
.then(res => res.json())
.then(result_geo => {
setData(result_geo)
console.log("Latitude is:", lat) // (GL)
console.log("Longitude is:", long) // (GL)
console.log(result_geo);
});
}, [lat, long])
return (
<div className="App">
{(typeof data.main != 'undefined') ? (
<div>
{data.map(item => <Weather weatherData={item}/>)}
</div>
): (
<div>
<Dimmer active>
<Loader>Loading..</Loader>
</Dimmer>
</div>
)}
</div>
);
}
CodePudding user response:
"display multiple cards": display arrays of Components
in React. So to display multiple you can use Array.map()
.
Ex:
const people = [
{ name: 'Harry' },
{ name: 'Ron' },
{ name: 'Hermione' },
]
...
return (
<>
{people.map((e, idx) => {
return (<span key={idx}>{e.name}</span>)
})}
</>
)
"pass that to weather.js": Not sure to get it. But when your parent component update a state the childrens using that state are going to rerender. So using a setData()
when you get your new api response should update weatherData
in the child component.