升级@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
相关产品推荐
相关产品推荐

