[英]React, make a second API call based on a state set by a first api call
我正在嘗試使用 OpenWeather API 構建一個天氣應用程序。我必須根據通過搜索定義location
的第一個 API 調用來獲取latitude
和longitude
。 我嘗試了async/await
和useEffect
鈎子,但在這兩種情況下都失敗了。
我的代碼如下。 我錯過了什么?
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.lat
和location.lon
被定義時調用searchFollowing()
:
useEffect(()=>{
if(location.lat && location.lon){
searchFollowing();
}
}, [location])
然后在search
function 中刪除 searchFollowing searchFollowing()
調用,就像現在在上面的useEffect
中調用它一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.