Home > Mobile >  Passing a second value through to js file
Passing a second value through to js file

Time:09-29

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} &deg;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.

  • Related