Вызов только один раз две функции в использованииEffect - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь вызвать две функции в моем хуке useEffect

import React, { useState, useEffect } from "react";

export const LocalWeather = () => {
  const APP_KEY = "XXX";
  const [userPlace, setUserPlace] = useState([]);
  const [localWeather, setLocalWeather] = useState([]);

  async function getUserData() {
    await fetch("http://ip-api.com/json")
      .then((res) => res.json())
      .then((data) => {
        setUserPlace({
          country: data.country,
          city: data.city,
        });
        console.log(data);
      })
      .catch((err) => console.log(err));
  }

  async function getLocalWeather() {
    await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
    )
      .then((res) => res.json())
      .then((data) => {
        setLocalWeather({
          temperature: Math.round(data.main.temp - 273.15),
        });
      })
      .catch((err) => console.log(err));
  }

  useEffect(() => {
    getUserData();
    getLocalWeather();
  });

  return (
    <div>
      <h3>
        Your current place is: {userPlace.country}, {userPlace.city}
      </h3>
      {localWeather.temperature ? (
        <h4>Temperature in your city is: {localWeather.temperature} &#8451;</h4>
      ) : null}
    </div>
  );
};

Когда я пытаюсь добавить [] к моему использованию, useEffect eslint автоматически меняет его на:

 useEffect(() => {
    getUserData();
    getLocalWeather();
  }, [getLocalWeather]);

Что следует Я делаю так, чтобы обе мои функции можно было вызывать только при первом рендере?

Спасибо за помощь!

1 Ответ

2 голосов
/ 03 мая 2020

Вы можете определить useEffect с пустой зависимостью, которая обеспечит выполнение функций только один раз

useEffect(() => {
    getUserData();
    getLocalWeather();
  }, []);

Однако, когда вы напишите это, как указано выше, eslint будет жаловаться на зависимость. Так что либо вы можете отключить предупреждение, например

useEffect(() => {
    getUserData();
    getLocalWeather();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

Подробнее об этом в этом посте: Как исправить предупреждение об отсутствующей зависимости при использовании useEffect React Hook?

Или иначе, если функции getUserData и getLocalWeather предназначены для использования только внутри useEffect, вы можете объявить их в useEffect

useEffect(() => {
    async function getUserData() {
        await fetch("http://ip-api.com/json")
          .then((res) => res.json())
          .then((data) => {
            setUserPlace({
              country: data.country,
              city: data.city,
            });
            console.log(data);
          })
          .catch((err) => console.log(err));
      }

      async function getLocalWeather() {
        await fetch(
          `https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
        )
          .then((res) => res.json())
          .then((data) => {
            setLocalWeather({
              temperature: Math.round(data.main.temp - 273.15),
            });
          })
          .catch((err) => console.log(err));
      }

      getUserData();
      getLocalWeather();
  }, []);

Однако, если по какой-то причине вы хотите использовать их и вне useEffect, а также не хотите отключать предупреждение, вы можете использовать useCallback для функций и добавить их в качестве зависимости

 const getUserData = useCallback(async function() {
  await fetch("http://ip-api.com/json")
    .then((res) => res.json())
    .then((data) => {
      setUserPlace({
        country: data.country,
        city: data.city,
      });
      console.log(data);
    })
    .catch((err) => console.log(err));
}, []);

const getLocalWeather = useCallback(async function getLocalWeather() {
    await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
    )
    .then((res) => res.json())
    .then((data) => {
      setLocalWeather({
        temperature: Math.round(data.main.temp - 273.15),
      });
    })
    .catch((err) => console.log(err));
}, []);


useEffect(() => {     
  getUserData();
  getLocalWeather();
}, [getUserData, getLocalWeather]);
...