簡體   English   中英

React,根據第一個 api 調用設置的 state 進行第二個 API 調用

[英]React, make a second API call based on a state set by a first api call

我正在嘗試使用 OpenWeather API 構建一個天氣應用程序。我必須根據通過搜索定義location的第一個 API 調用來獲取latitudelongitude 我嘗試了async/awaituseEffect鈎子,但在這兩種情況下都失敗了。

我的代碼如下。 我錯過了什么?

import { 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;

您缺少的是,當您調用searchFollowing()時,React 尚未重新渲染,因此不會更新location 你可以有一個useEffect來監聽location ,並在location.latlocation.lon被定義時調用searchFollowing()

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

然后在search function 中刪除 searchFollowing searchFollowing()調用,就像現在在上面的useEffect中調用它一樣。

在此處輸入圖像描述

感謝@yousoumar,下面的代碼解決了這個問題。 我會嘗試第二個。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM