首页 > 解决方案 > 如何阻止多个重新渲染执行多个 api 调用 useEffect?

问题描述

我是反应功能组件的新手,我正在尝试在页面加载时获取多个城市的天气数据,但 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();
    }, []);

标签: javascriptreactjsaxiosreact-hooksreact-functional-component

解决方案


您可以使该fetchData函数在不更新状态的情况下返回您需要的数据,然后您可以获取 x 数量的城市,并且仅当所有请求完成更新状态时。

请注意,如果Promise.all中的请求之一失败,它将进入catch块而不返回任何数据,基本上全有或全无

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()
  }, [])
}

推荐阅读