使用 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