[英]React, make a second API call based on a state set by a first api call
I am trying to build a weather app with OpenWeather API. I have to get the latitude
and longitude
based on a first API call that define the location
by search.我正在尝试使用 OpenWeather API 构建一个天气应用程序。我必须根据通过搜索定义
location
的第一个 API 调用来获取latitude
和longitude
。 I have tried async/await
and useEffect
hook but failed in both cases.我尝试了
async/await
和useEffect
钩子,但在这两种情况下都失败了。
My code is below.我的代码如下。 What am I missing?
我错过了什么?
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;
What you are missing is that when you are calling searchFollowing()
, React did not yet re-render, therefore location
wouldn't be updated.您缺少的是,当您调用
searchFollowing()
时,React 尚未重新渲染,因此不会更新location
。 You could have an useEffect
that would listen to location
, and call searchFollowing()
there when location.lat
and location.lon
are defined:你可以有一个
useEffect
来监听location
,并在location.lat
和location.lon
被定义时调用searchFollowing()
:
useEffect(()=>{
if(location.lat && location.lon){
searchFollowing();
}
}, [location])
Then remove searchFollowing()
call inside search
function, as now you call it inside the above useEffect
.然后在
search
function 中删除 searchFollowing searchFollowing()
调用,就像现在在上面的useEffect
中调用它一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.