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

React严格模式下useEffect异步调用报DOMException错误求助

解决React严格模式下useEffect异步GraphQL请求的DOMException错误

这个问题本质是React 18严格模式在开发环境下的特殊行为导致的:它会模拟组件「挂载-卸载-重新挂载」的过程,用来检测未清理的副作用。当useEffect因为依赖变化重新执行时,旧的异步请求还未完成,React会自动中止该请求的AbortSignal,如果你的代码没处理这个信号,就会抛出DOMException: signal is aborted without reason错误。

解决方案:给异步请求添加中止信号处理

需要两步修改:给GraphQL请求传入AbortSignal,并在useEffect的清理函数中主动中止未完成的请求。

1. 修改useEffect代码,添加AbortController

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;

  const loadTags = async () => {
    try {
      // 把signal传给fetchTags
      const { data } = await fetchTags(signal);
      // 确保请求未被中止时再更新状态,避免过时的状态变更
      if (!signal.aborted) {
        setTags([...(data?.tags || [])]);
      }
    } catch (err) {
      // 忽略AbortError,这是清理时的预期行为
      if (err.name !== 'AbortError') {
        console.error('标签加载失败:', err);
      }
    }
  };

  loadTags();

  // 组件卸载或useEffect重新执行时,中止请求
  return () => controller.abort();
}, [current, fetchTags]);

2. 更新fetchTags函数,支持AbortSignal

以Apollo Client为例,需要在请求上下文传入signal:

// 假设fetchTags是基于Apollo Client封装的查询函数
const fetchTags = async (signal) => {
  return await client.query({
    query: YOUR_TAGS_GRAPHQL_QUERY,
    context: { signal }, // 将中止信号传入请求
  });
};

说明

  • 这个错误不是依赖包的问题,而是React 18严格模式的新行为暴露了代码中未处理请求中止的问题。
  • 生产环境下严格模式的双重执行逻辑会被关闭,但添加中止信号处理依然是最佳实践,能避免组件卸载后更新状态导致的内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:25:23