Отменить асин c запрос на выборку в React Native с помощью Expo - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть приложение React Native, созданное с помощью Expo (v35.0.0). У меня есть простая функция asyn c (loadData()), которая запускает запрос выборки (через fetchData()) к API, чтобы ответ затем передавался в мое хранилище с избыточностью:

const loadData = async (id, token) => {
  setIsLoading(true);
  try {
    await dispatch(fetchData(id, token));
  } catch (error) {
    setHasError(true);
  }
  setIsLoading(false);
};

useEffect(() => {
  loadData(user.client.id, user.token);
}, [user.client.id]);

Однако, когда пользователь выходит из системы, мы получаем предупреждение: «Не удается выполнить обновление состояния React для неустановленного компонента», что, как я понимаю, связано с отменой асинхронного запроса c.

У меня есть попытался реализовать подход AbortController (как изложено в этой статье: https://dev.to/iquirino/react-hook-clean-up-useeffect-24e7), однако затем мы представляем ошибку с указанием AbortConroller неизвестно.

Я думал, что поддержка AbortConroller будет в Expo сейчас, так как она была добавлена ​​в React Native еще в июле прошлого года в рамках выпуска v0.60.

Итак, возможно ли реализовать AbortController в Expo для отмены асинхронного запроса c? Если нет, как мне go отменить запрос , чтобы избежать предупреждения (и утечки памяти)?

1 Ответ

1 голос
/ 19 февраля 2020

Поскольку ваш dispatch является асинхронным c, он может завершиться до 1010 * после размонтирования компонента.

Внутри useEffect вы можете вернуть функцию, которую вы вызываете для очистки. Здесь вы можете установить флаг, чтобы указать, что компонент больше не подключен, и если этот флаг указывает, что он больше не подключен, вы можете указать ему не обновлять состояние.

например.

let mounted = true;

const loadData = async (id, token) => {
  setIsLoading(true);
  try {
    await dispatch(fetchData(id, token));
  } catch (error) {
    if (mounted) setHasError(true);
  }
  if (mounted) setIsLoading(false);
};

useEffect(() => {
  loadData(user.client.id, user.token);
  return () => mounted = false;
}, [user.client.id]);
...