You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Expo v35.0.0的React Native中如何取消异步Fetch请求?

Can't use AbortController in Expo v35.0.0? How to cancel async requests to avoid state update warnings?

问题根源

你遇到的AbortController is unknown错误是因为Expo v35.0.0对应的React Native版本是0.59.x,而AbortController是在React Native 0.60版本才正式引入的,所以你的当前环境并不支持这个API。

至于组件卸载后出现的Can't perform a React state update on an unmounted component警告,确实是因为异步请求还在进行时组件已经被卸载,后续的setIsLoading/setHasError尝试更新已卸载组件的状态导致的。

解决方案

我们分两种场景来解决这个问题:

1. 升级Expo版本(推荐,若项目允许)

如果你的项目没有强依赖Expo v35的特性,建议升级到Expo v36.0.0及以上版本(对应React Native 0.60+),这样就能原生支持AbortController了。

升级后,你可以这样修改代码来实现请求取消:

const loadData = async (id, token, abortController) => {
  setIsLoading(true);
  try {
    // 将signal传入fetch请求(假设fetchData内部使用了fetch API)
    await dispatch(fetchData(id, token, abortController.signal));
  } catch (error) {
    // 排除取消请求的错误
    if (error.name !== 'AbortError') {
      setHasError(true);
    }
  }
  setIsLoading(false);
};

useEffect(() => {
  const abortController = new AbortController();
  loadData(user.client.id, user.token, abortController);

  // 组件卸载时取消请求
  return () => abortController.abort();
}, [user.client.id]);

注意:需要确保你的fetchData函数内部在调用fetch时传入了signal参数,比如:

const fetchData = (id, token, signal) => async (dispatch) => {
  const response = await fetch(`your-api-url/${id}`, {
    method: 'GET',
    headers: { Authorization: `Bearer ${token}` },
    signal // 传入signal
  });
  // 后续处理逻辑...
};

2. 在Expo v35下的替代方案

如果无法升级Expo版本,我们可以用以下两种方式避免状态更新警告:

方案A:使用组件挂载状态标记

在组件内维护一个isMounted状态,在组件卸载时标记为false,异步操作完成后先检查该标记再执行状态更新:

const [isMounted, setIsMounted] = useState(true);

useEffect(() => {
  return () => setIsMounted(false); // 组件卸载时标记为false
}, []);

const loadData = async (id, token) => {
  setIsLoading(true);
  try {
    await dispatch(fetchData(id, token));
  } catch (error) {
    if (isMounted) { // 检查组件是否仍挂载
      setHasError(true);
    }
  }
  if (isMounted) { // 检查组件是否仍挂载
    setIsLoading(false);
  }
};

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

方案B:使用axios的CancelToken取消请求

如果你的项目可以切换到axios发起请求,axios提供了CancelToken机制来取消请求,这在React Native 0.59环境下是可行的:

首先安装axios:

expo install axios

然后修改代码:

import axios from 'axios';

const loadData = async (id, token, cancelToken) => {
  setIsLoading(true);
  try {
    await dispatch(fetchData(id, token, cancelToken));
  } catch (error) {
    // 排除取消请求的错误
    if (!axios.isCancel(error)) {
      setHasError(true);
    }
  }
  setIsLoading(false);
};

useEffect(() => {
  const source = axios.CancelToken.source();
  loadData(user.client.id, user.token, source.token);

  // 组件卸载时取消请求
  return () => source.cancel('Component unmounted, canceling request');
}, [user.client.id]);

对应的fetchData函数修改为:

const fetchData = (id, token, cancelToken) => async (dispatch) => {
  const response = await axios.get(`your-api-url/${id}`, {
    headers: { Authorization: `Bearer ${token}` },
    cancelToken // 传入CancelToken
  });
  // 后续处理逻辑...
};

总结

  • 若能升级Expo版本,优先使用原生的AbortController方案,这是最标准的现代异步请求取消方式。
  • 若无法升级,使用组件挂载标记或axios的CancelToken都能有效避免状态更新警告和潜在的内存泄漏。

内容的提问来源于stack exchange,提问作者Sheixt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:34:08