Реагируйте программно на отзыв о крючке - PullRequest
1 голос
/ 28 октября 2019

https://codesandbox.io/s/react-hooks-usefetch-cniul

Пожалуйста, см. Выше URL для очень упрощенной версии моего кода.

Я хочу иметь возможность получать данные из API с помощью моего хука, в течение интервала (в основном опрашивают конечную точку для данных).

Я хочу просто иметь возможность вызывать что-то вроде refetch (как я показал в коде в качестве комментария), что по сути просто вызовет fetchData снова и обновите состояние соответствующим ответом.

Какой лучший способ сделать это? Единственный способ, о котором я могу подумать, - это добавить в ловушку переменную checker, которая была бы своего рода uuid (возможно Math.random()), вернуть setChecker как refetch и просто добавить checker кмассив как 2-й аргумент useEffect для управления перерисовкой. Поэтому, когда вы вызываете refetch, он вызывает setChecker, который обновляет случайное число (checker), а затем функция запускается снова.

Очевидно, это звучит «хакерски», должен быть более хороший способ сделатьэто - есть идеи?

Ответы [ 3 ]

0 голосов
/ 28 октября 2019
<code>import React, { useEffect, useState, useCallback } from "react";
import ReactDOM from "react-dom";

const url = "https://api.etilbudsavis.dk/v2/dealerfront?country_id=DK";

function useFetch() {
  const [data, setDataState] = useState(null);
  const [loading, setLoadingState] = useState(true);
  const refetch = useCallback(() => {
    function fetchData() {
      console.log("fetch");
      setLoadingState(true);
      fetch(url)
        .then(j => j.json())
        .then(data => {
          setDataState(data);
          setLoadingState(false);
        });
    }
    fetchData();
  }, []);

  return [
    {
      data,
      loading
    },
    refetch
    // fetchData <- somehow return ability to call fetchData function...
  ];
}

function App() {
  const [
    { data, loading },
    refetch
    // refetch
  ] = useFetch();

  useEffect(() => {
    const id = setInterval(() => {
      // Use the refetch here...
      refetch();
    }, 5000);
    return () => {
      clearInterval(id);
    };
  }, [refetch]);

  if (loading) return <h1>Loading</h1>;
  return (
    <>
      <button onClick={refetch}>Refetch</button>
      <code style={{ display: "block" }}>
        <pre>{JSON.stringify(data[0], null, 2)}
);} const rootElement = document.getElementById ("root");ReactDOM.render (, rootElement);
0 голосов
/ 29 октября 2019

Может быть, сработает следующее, ему нужно внести некоторые коррективы, чтобы использовать функцию извлечения, но вы все равно можете вызывать его как обычно в других местах.

//maybe you can pass url as well so you can use
//  it with other components and urls
function useFetch(refresh) {
  //code removed
  useEffect(() => {
    //code removed
  }, [refresh]);
  //code removed
}

const [refresh, setRefresh] = useState({});
const [{ data, loading }] = useFetch(refresh);
useEffect(() => {
  const interval = setInterval(
    () => setRefresh({}), //forces re render
    5000
  );
  return () => clearInterval(interval); //clean up
});
0 голосов
/ 28 октября 2019

Если вы хотите, чтобы проводился постоянный опрос, я думаю, вы можете переместить setInterval() в крючок следующим образом:

function useFetch() {
  const [data, setDataState] = useState(null);
  const [loading, setLoadingState] = useState(true);
  useEffect(() => {
    function fetchData() {
      setLoadingState(true);
      fetch(url)
        .then(j => j.json())
        .then(data => {
          setDataState(data);
          setLoadingState(false);
        });
    }

    const interval = setInterval(() => {
      fetchData();
    }, 5000);

    fetchData();

    return () => clearInterval(interval);
  }, []);

  return [
    {
      data,
      loading
    }
  ];
}

Не забудьте включить return () => clearInterval(interval);, чтобы очистить крючокправильно.

...