React Asyn c Функция, заключенная в UseEffect - PullRequest
0 голосов
/ 17 июня 2020

Я не понимаю, как работает функция asyn c.

console.log возвращает ошибку, потому что data.rates еще не существует. Но я подумал, что, поскольку функция useEffect является asyn c, все, что находится под ней, будет вызываться после завершения asyn c.

function App() {
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setData(result.data);
    })();
  }, []);

  console.log(data.rates); <-- Error data.rates does not exist
  return <div>{!data ? "Loading..." : "Hello"}</div>;
}

Ответы [ 3 ]

2 голосов
/ 17 июня 2020

Мне кажется, что ни один из ответов на самом деле не отвечает на вопрос.

useEffect не останавливает поток выполнения, не имеет значения, что вы делаете внутри переданного ему обратного вызова. Таким образом, выполняется console.log(data.rates), а затем, когда компонент монтируется, выполняется обратный вызов, переданный в useEffect. Поскольку состояние изменяется в обратном вызове (setData(result.data)), это вызывает повторный рендеринг, и на этот раз вы должны увидеть, что правильное значение регистрируется без каких-либо ошибок.

1 голос
/ 17 июня 2020

Ваше предположение на самом деле верно, useEffect в этом сценарии будет запущен, когда компонент смонтирован , что означает, что console.log будет вызываться дважды - сначала с начальным значением (которое не определено), второе - после useEffect выполнил побочный эффект, когда данные фактически установлены (setData) после выполнения запроса. Обычно вы предоставляете состояние «загрузка», когда данные устарели.

function App() {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      setLoading(true);
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setLoading(false);
      setData(result.data);
    })();
  }, []);

  if (loading) return <div>Fetching data...</div>

  return <div>Hello</div>;
}
0 голосов
/ 17 июня 2020

Попробуйте сделать это (я вроде как создал обходной путь)

function App() {
    const [data, setData] = useState();

    useEffect(()=>{
        const setObtainedData=async()=>{
            const result = await axios.get("https://open.exchangerate-api.com/v6/latest");
            setData(result.data);
        };
        setObtainedData();
    },[]);

    if(data){
        console.log(data.rates);
    }
    return <div>{!data ? "Loading..." : "Hello"}</div>;
};
...