Отмена асинхронного запроса с помощью ловушки useInterval - PullRequest
0 голосов
/ 06 октября 2019

Отмена запроса очень проста с помощью очистки useEffect

useEffect(() => {
  let ignore = false;
  fetchData(id).then(data => {
    if (!ignore) {
      setData(data);
    }
  });
  return () => (ignore = true);
}, [id]);

Я хочу сделать что-то подобное, но мне нужно опросить данные с помощью useInterval

Iхотите опросить данные с помощью fetchData(id) и игнорировать возвращенный ответ, если запрос сработал, но id изменилось до разрешения ответа.

1 Ответ

0 голосов
/ 06 октября 2019

Вот useInterval, который я придумал

function (callback, options, cleanup) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (options.delay !== null) {
      let id = setInterval(tick, options.delay);
      return () => {        
        clearInterval(id);
        cleanup && cleanup();
      }
    }
    return () => cleanup && cleanup();
  }, [options]);
}

И я использую его так

const [fetchOptions, setFetchOptions] = useState({delay: 5000, id: 'someid'});

let ignore = false;
useInterval(
  () => {
    fetchData(fetchOptions.id).then(data => {
      if (!ignore) {
        setData(data);
      }
    });
  },
  fetchOptions,
  () => (ignore = true),
);

Я не уверен, есть ли лучший способ написать это. Меня беспокоит то, что переменная ignore находится в контексте функции / компонента. В примере кода вопроса, переменная ignore находится внутри useEffect и чувствует себя чище.

Недостатком этого подхода является то, что fetchOptions должна быть переменной useState, иначе она будет сбрасывать ловушку useInterval при каждом рендеринге, еслиэто была просто константа в функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...