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

升级@apollo/client至3.9.3后stopPolling失效问题求助

Apollo Client 3.9.3 中 startPolling/stopPolling 失效的解决建议

先修正代码中的明显错误

你提供的示例代码存在递归调用自定义hook的问题:const { startPolling, stopPolling, ...queryResult } = useMyPolledQuery({...}),这会导致无限循环,也是轮询异常的潜在原因之一。首先需要将这里的useMyPolledQuery替换为Apollo官方的useQuery(传入对应的查询文档)。

方案1:使用受控pollInterval替代startPolling/stopPolling

Apollo Client 3.8+版本后,轮询的内部逻辑有调整,startPolling/stopPolling这类命令式API容易因组件重渲染丢失引用,改用受控状态绑定pollInterval是更可靠的方式:

import { useQuery, useState } from '@apollo/client';
// 导入你的查询文档
import MY_POLLED_QUERY from './your-query-document';

export function useMyPolledQuery({
  additionalOnCompleted,
  skip,
  variables,
  fetchPolicy = 'cache-and-network',
}: Type) {
  // 用状态控制轮询间隔:null表示停止,数值表示轮询间隔毫秒数
  const [pollInterval, setPollInterval] = useState<number | null>(null);

  const queryResult = useQuery(MY_POLLED_QUERY, {
    skip,
    variables,
    onCompleted(data) {
      additionalOnCompleted?.(data);
      const result = data?.myData;
      if (result?.status !== myData.Loading) {
        // 满足条件时停止轮询
        setPollInterval(null);
        return;
      }
      // 继续轮询
      setPollInterval(1000);
    },
    onError(error) {
      Sentry.captureException(error);
      // 出错时停止轮询
      setPollInterval(null);
    },
    fetchPolicy,
    // 直接绑定受控状态
    pollInterval,
  });

  return queryResult;
}

方案2:用Ref保存stopPolling引用(兼容命令式场景)

如果必须保留startPolling/stopPolling的使用方式,需要用useRef保存stopPolling的引用,避免组件重渲染后引用失效:

import { useQuery, useRef, useEffect } from '@apollo/client';
import MY_POLLED_QUERY from './your-query-document';

export function useMyPolledQuery({
  additionalOnCompleted,
  skip,
  variables,
  fetchPolicy = 'cache-and-network',
}: Type) {
  // 用Ref保存stopPolling函数引用
  const stopPollingRef = useRef<(() => void) | null>(null);

  const { startPolling, stopPolling, ...queryResult } = useQuery(MY_POLLED_QUERY, {
    skip,
    variables,
    onCompleted(data) {
      additionalOnCompleted?.(data);
      const result = data?.myData;
      if (result?.status !== myData.Loading) {
        // 通过Ref调用stopPolling
        stopPollingRef.current?.();
        return;
      }
      startPolling(1000);
    },
    onError(error) {
      Sentry.captureException(error);
      stopPollingRef.current?.();
    },
    fetchPolicy,
  });

  // 每次组件渲染时更新Ref的引用
  useEffect(() => {
    stopPollingRef.current = stopPolling;
  }, [stopPolling]);

  return queryResult;
}

关键注意事项

  • 避免同时使用startPolling/stopPolling和pollInterval属性,两者会互相干扰导致轮询状态异常。
  • Apollo Client 3.8+对轮询的内部调度逻辑做了优化,命令式API的依赖引用容易因组件重渲染丢失,优先推荐受控pollInterval的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:56:00