Функция очистки завершается неудачно в первый раз, используя AbortController - PullRequest
0 голосов
/ 09 апреля 2020

Я использую AbortController, чтобы отменить обещание fetch при размонтировании жизненного цикла React. По какой-то причине очистка не работает В ПЕРВЫЙ РАЗ, элемент размонтируется .

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;
    fetch(`https://pokeapi.co/api/v2/pokemon/${name}`, { signal })
      .then(sleeper(1)) // Create some latency
      .then(res => res.json())
      .then(response => {
        setData(response);
      })
      .catch(error => {
        setData(error);
      });
    return () => {
      controller.abort();
    };
  }, [name]);

Демо

Выполните следующие шаги:

  1. Доступ к демонстрационной ссылке.
  2. Нажмите кнопку Show/hide pokemon ДВАЖДЫ быстро, чтобы принудительно прервите дочернего элемента Pokemon реагирующий элемент.
  3. Проверьте ошибку в консоли: Can't perform a React state update on an unmounted component
  4. Повторите шаг 2. Нажмите Show/hide pokemon ДВАЖДЫ быстро, чтобы принудительно прервать дочернего Pokemon элемента реагирования.
  5. Ошибки не найдены на этот раз и последующие попытки. Почему?

1 Ответ

1 голос
/ 09 апреля 2020

AbortController

Примечание: Когда вызывается abort(), обещание fetch() отклоняется с DOMException с именем AbortError.

Когда компонент отключается и abort вызывается, fetch отклоняется с ошибкой. Ошибка обнаружена, и этот код пытается установить состояние с ошибкой. Пропуск этого обновления состояния ошибки удаляет ошибку реакции.

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;
  fetch(`https://pokeapi.co/api/v2/pokemon/${name}`, { signal })
    .then(sleeper(1)) // Create some latency
    .then(res => res.json())
    .then(response => {
      setData(response);
    })
    .catch(error => {
      setData(error); // <-- this is being called after component unmounts!
    });
  return () => {
    controller.abort();
  };
}, [name]);

Я также готов поспорить, что ошибка возникает каждый раз, но реакция просто выводит первый и выводит глушение для последующие ошибки.

...