Home > front end >  Make a second API call based on first api call response in React with hooks
Make a second API call based on first api call response in React with hooks

Time:02-03

I am trying to build a weather app with open weather API. There is a problem with the first call I have to get the value latitude and longitude from the first API to make a second API call. I have tried async / await but can't get the correct structure this code to work I also tried useEffect hook but failed again.

My code is below. What am I missing?

import React, { useEffect, useState } from 'react';

const api = {
  key: `${process.env.REACT_APP_API_KEY}`,
  base: 'https://api.openweathermap.org/data/2.5/'
}

function App() {

  const [query, setQuery] = useState('');
  const [weather, setWeather] = useState({});
  const [location, setLocation] = useState({ lat: '', lon: '' });
  const [following, setFollowing] = useState([]);




  const search = async (e) => {
    if (e.key === 'Enter') {
      await fetch(`${api.base}weather?q=${query}&units=metric&appid=${api.key}&lang=tr`)
        .then(res => res.json())
        .then(result => {
          setWeather(result);
          setQuery('');
          setLocation(result.coord);
          console.log(result);
          searchFollowing();
        }
        )
    }
  }

    const searchFollowing = async () => {
     await  fetch(`${api.base}onecall?lat=${location.lat}&lon=${location.lon}&units=metric&exclude=hourly,minutely&appid=${api.key}`)
        .then(res => res.json())
        .then(result2 => {
          const array = result2.daily.slice(1, 6);
          console.log(following);
          setFollowing(array);
          // following == array
        }
        )
    }



  const integer = (number) => {
    return Math.floor(Math.round(number));
  }

  const mapped = (following) => {
    following = [...following];
    return following.map((item, idx) => {
      const icon = item.weather[0].icon;
      const day = integer(item.temp.day);
      const night = integer(item.temp.night);
      return (
        <div key={idx} className="box">
          <img
            src={`http://openweathermap.org/img/wn/${icon}.png`}
            alt='weather'
            width={80}
            height={80}
          />
          <h3>Day {day} °C</h3>
          <h3>Night {night} °C</h3>
        </div>
      )
    })
  }

  const dateBuild = (d) => {
    let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
    let days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']

    let day = days[d.getDay()]
    let date = d.getDate()
    let month = months[d.getMonth()]
    let year = d.getFullYear()

    return `${day} ${date} ${month} ${year}`
  }


  return (
    <div className={(typeof weather.main !== 'undefined') ?
      ((weather.main.temp > 25) ? 'App hot' :
        ((weather.main.temp < 25 && weather.main.temp > 5) ?
          'App warm' : 'App')) : 'App'}>
      <main>
        <div className="search-box">
          <input
            type="text"
            className="search-bar"
            placeholder="Search for a location..."
            onChange={e => setQuery(e.target.value)}
            onKeyPress={search}
            value={query}
          />
        </div>
        {(typeof weather.main != "undefined") ? (
          <div>
            <div className="location-box">
              <div className="location">
                {weather.name}, {weather.sys.country}
              </div>
              <div className="date"> {dateBuild(new Date())}
              </div>
            </div>
            <div className="weather-box">
              <div className="temp">
                {Math.round(weather.main.temp)}°C
                <img
                  src={`http://openweathermap.org/img/wn/${weather.weather[0].icon.slice(0, 2)}d.png`}
                  alt='weather'
                  width={80}
                  height={80}
                />
              </div>
              <div className="weather">
                <p>
                  <span>Hissedilen</span>
                  {Math.floor(weather.main.feels_like)} °C
                </p>
                <p>
                  <span>Şu an</span>
                  {weather.weather[0].description}
                </p>
                <p>
                  <span>Basınç</span>
                  {weather.main.pressure} mb
                </p>
                <p>
                  <span>Rüzgar </span>
                  {Math.floor(weather.wind.speed)} km/h
                </p>
                <p>
                  <span>En fazla</span>
                  {Math.floor(weather.main.temp_max)} °C
                </p>
                <p>
                  <span>En az</span>
                  {Math.floor(weather.main.temp_min)} °C
                </p>
              </div>
            </div>
            <div className="followingdays">
              {mapped(following)}
            </div>
          </div>) : ('')}
      </main>
    </div>
  );
}

export default App;

CodePudding user response:

What you are missing is that when you are calling searchFollowing(), React did not yet re-render, therefore location wouldn't be get updated. A way to do it is this :

import React, { useEffect, useState } from 'react';

const api = {
  key: `${process.env.REACT_APP_API_KEY}`,
  base: 'https://api.openweathermap.org/data/2.5/'
}

function App() {

  const [query, setQuery] = useState('');
  const [weather, setWeather] = useState({});
  const [location, setLocation] = useState({ lat: '', lon: '' });
  const [following, setFollowing] = useState([]);


  useEffect(()=>{
  
    if(location.lat && location.lon){
      searchFollowing();
    }
  }, [location])

  const search = (e) => {
    if (e.key === 'Enter') {
      fetch(`${api.base}weather?q=${query}&units=metric&appid=${api.key}&lang=tr`)
        .then(res => res.json())
        .then(result => {
          setWeather(result);
          setQuery('');
          setLocation(result.coord);
        }
        )
    }
  }

    const searchFollowing = () => {
     fetch(`${api.base}onecall?lat=${location.lat}&lon=${location.lon}&units=metric&exclude=hourly,minutely&appid=${api.key}`)
        .then(res => res.json())
        .then(result2 => {
          const array = result2.daily.slice(1, 6);
          console.log(following);
          setFollowing(array);
          // following == array
        }
        )
    }

CodePudding user response:

enter image description here

The code below solved the problem thanks to @yousoumar. I will try second one.

  useEffect(()=>{
  
    if(location.lat && location.lon){
      searchFollowing();
    }
  }, [location])

  •  Tags:  
  • Related