使用 Expo 取消 React Native 中的异步获取请求

Posted

技术标签:

【中文标题】使用 Expo 取消 React Native 中的异步获取请求【英文标题】:Cancel async fetch request in React Native using Expo 【发布时间】:2020-02-19 12:31:42 【问题描述】:

我有一个使用 Expo (v35.0.0) 构建的 React Native 应用程序。我有一个简单的异步函数 (loadData()),它对 API 运行 fetch(通过 fetchData())请求,然后将响应传递到我的 redux 存储中:

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 状态更新”,我理解这是因为异步请求已被取消。

我已尝试实施AbortController 方法(如本文所述:https://dev.to/iquirino/react-hook-clean-up-useeffect-24e7),但随后出现错误,指出AbortConroller 未知。

我认为对 AbortConroller 的支持现在将在 Expo 中,因为它作为 v0.60 版本的一部分于去年 7 月被添加到 React Native。

那么,是否可以在 Expo 中实现AbortController 来取消异步请求?如果没有,我应该如何取消请求以避免警告(和内存泄漏)?

【问题讨论】:

在你的useEffect钩子里,你可以返回一个清理函数,用这个你可以设置一个标志,然后如果它被设置了abort而不是调用setState.. 【参考方案1】:

因为您的dispatch 是异步的,所以它可能会在您的组件卸载后完成。

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]);

【讨论】:

太棒了,谢谢@Keith。仍然有兴趣知道为什么 AbortController 在 Expo 中无法运行,但这解决了我的问题。

以上是关于使用 Expo 取消 React Native 中的异步获取请求的主要内容,如果未能解决你的问题,请参考以下文章

Stripe 付款后如何从 Webview 重定向到 React Native Expo 应用程序?

尝试在 create-react-native-app 项目 (expo) 中使用 react-native-fs

无法使用 react-native-svg 或 Svg/expo 让 Svg 显示在 react-native 中

使用 react-native (expo) 切换手电筒

React-native (expo) - 无效类型

使用 Relay Modern 创建-react-native-app / expo