Реагировать useEffect hook и Async / await собственную функцию извлечения данных? - PullRequest
1 голос
/ 05 марта 2019

Я попытался создать функцию для извлечения данных с сервера, и она работает.Но я не уверен, что это правильный путь?

Я создал компонент функции для извлечения данных, используя useState , useEffect и Async / Await :

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

const Fetch = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    const fetchData = async () => {
      let res = await fetch(
        "https://api.coindesk.com/v1/bpi/currentprice.json" //example and simple data
      );
      let response = await res.json();
      setData(response.disclaimer); // parse json
      console.log(response);
    };
    fetchData();
  }, []);
  return <div>{data}</div>;
};

export default Fetch; // don't run code snippet, not working, this component must be imported in main

Там, где я не уверен, находится место , где - вызывают fetchData .Я делаю это внутри useEffect?Правильное место?И этот звонок произойдет только один?Потому что я использую [] ?

Вообще, как бы вы сделали что-то подобное?

Ответы [ 2 ]

1 голос
/ 09 марта 2019

В целом, вы движетесь в правильном направлении. Для извлечения данных вы должны использовать useEffect и передавать [] в качестве второго аргумента, чтобы убедиться, что он срабатывает только при первоначальном монтировании.

Я полагаю, что вы могли бы извлечь выгоду из развязки функции fetchJson и сделать ее более общей:

const fetchJson = async (url) => {
  const response = await fetch(url);
  return response.json();
};

const Fetch = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchJson("https://api.coindesk.com/v1/bpi/currentprice.json")
      .then(({ disclaimer }) => setState(disclaimer));
  }, []);

  return <div>{data}</div>;
};
0 голосов
/ 05 июня 2019

Другим вариантом является использование функции, вызывающей себя:

const Fetch = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    (async () => {
      let res = await fetch(
        "https://api.coindesk.com/v1/bpi/currentprice.json" //example and simple data
      );
      let response = await res.json();
      setData(response);
    })();
  }, []);
  return <div>{data}</div>;
};

Предложение о выделении логики выборки для отдельной функции является хорошей идеей и может быть сделано следующим образом:

const Fetch = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    (async () => {
      let response= await fetchData("https://api.coindesk.com/v1/bpi/currentprice.json");
      setData(response);
    })();
  }, []);
  return <div>{data}</div>;
};

const fetchData = async (url) => {
  const response = await fetch(url);
  const json = await response.json();

  return json;
};

И еще один вариант - создать функцию-оболочку вокруг useEffect, которая запускает для вас асинхронную функцию, подобную этой:

export function useAsyncEffect(effect: () => Promise<any>) {
  useEffect(() => {
    effect().catch(e => console.warn("useAsyncEffect error", e));
  });
}
...