如何阻止多次重新渲染进行多次 api 调用 useEffect?
how to stop multiple re-renders from doing multiple api calls useEffect?
我是 React 功能组件的新手,我试图在页面加载时获取多个城市的天气数据,但 useEffect 现在重新渲染每个调用。我如何编写此代码才能使 useEffect 不会导致重新渲染?
function App() {
const [data, setData] = useState([]);
const [activeWeather, setActiveWeather] = useState([]);
useEffect(() => {
const key = process.env.REACT_APP_API_KEY;
const fetchData = async (city) => {
const res = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`);
setData((data) => [
...data,
{ description: res.data.weather[0].description, icon: res.data.weather[0].icon, temp: res.data.main.temp, city: res.data.name, country: res.data.sys.country, id: res.data.id },
]);
};
const fetchCities = () => {
const cities = [fetchData("Ottawa"), fetchData("Toronto"), fetchData("Vancouver"), fetchData("California"), fetchData("London")];
Promise.all(cities).catch((err) => {
console.log(err);
});
};
fetchCities();
}, []);
您可以使 fetchData
函数在不更新状态的情况下 return 您需要的数据,然后您可以获取 x 个城市,并且仅当所有请求完成时才更新状态。
请注意,如果 Promise.all 中的其中一个请求失败,它将转到 catch
块而不会 return 返回任何数据,基本上是全有或全无
const key = process.env.REACT_APP_API_KEY
const fetchCity = async city => {
const { data } = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`,
)
return {
description: data.weather[0].description,
icon: data.weather[0].icon,
temp: data.main.temp,
city: data.name,
country: data.sys.country,
id: data.id,
}
}
function App() {
const [cities, setCities] = useState([])
const [activeWeather, setActiveWeather] = useState([])
useEffect(() => {
const fetchCities = async () => {
const citiesData = await Promise.all(
['Ottawa', 'Toronto', 'Vancouver'].map(fetchCity),
)
setCities(prevState => prevState.concat(citiesData))
}
fetchCities()
}, [])
}
您可以使用 Promise.all
然后调用 setData
一次。像这样:
useEffect(() => {
const fetchCity = (city) => axios.get(`${base}/${city}`);
const cities = ["Ottawa", "Toronto"];
const promises = cities.map(fetchCity);
Promise.all(promises).then((responses) => {
setData(cities.map((city, index) => ({ city, ...responses[index] })));
});
}, []);
我是 React 功能组件的新手,我试图在页面加载时获取多个城市的天气数据,但 useEffect 现在重新渲染每个调用。我如何编写此代码才能使 useEffect 不会导致重新渲染?
function App() {
const [data, setData] = useState([]);
const [activeWeather, setActiveWeather] = useState([]);
useEffect(() => {
const key = process.env.REACT_APP_API_KEY;
const fetchData = async (city) => {
const res = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`);
setData((data) => [
...data,
{ description: res.data.weather[0].description, icon: res.data.weather[0].icon, temp: res.data.main.temp, city: res.data.name, country: res.data.sys.country, id: res.data.id },
]);
};
const fetchCities = () => {
const cities = [fetchData("Ottawa"), fetchData("Toronto"), fetchData("Vancouver"), fetchData("California"), fetchData("London")];
Promise.all(cities).catch((err) => {
console.log(err);
});
};
fetchCities();
}, []);
您可以使 fetchData
函数在不更新状态的情况下 return 您需要的数据,然后您可以获取 x 个城市,并且仅当所有请求完成时才更新状态。
请注意,如果 Promise.all 中的其中一个请求失败,它将转到 catch
块而不会 return 返回任何数据,基本上是全有或全无
const key = process.env.REACT_APP_API_KEY
const fetchCity = async city => {
const { data } = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`,
)
return {
description: data.weather[0].description,
icon: data.weather[0].icon,
temp: data.main.temp,
city: data.name,
country: data.sys.country,
id: data.id,
}
}
function App() {
const [cities, setCities] = useState([])
const [activeWeather, setActiveWeather] = useState([])
useEffect(() => {
const fetchCities = async () => {
const citiesData = await Promise.all(
['Ottawa', 'Toronto', 'Vancouver'].map(fetchCity),
)
setCities(prevState => prevState.concat(citiesData))
}
fetchCities()
}, [])
}
您可以使用 Promise.all
然后调用 setData
一次。像这样:
useEffect(() => {
const fetchCity = (city) => axios.get(`${base}/${city}`);
const cities = ["Ottawa", "Toronto"];
const promises = cities.map(fetchCity);
Promise.all(promises).then((responses) => {
setData(cities.map((city, index) => ({ city, ...responses[index] })));
});
}, []);