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

useLazyQuery的onCompleted回调在状态变更后未触发求助

问题分析与解决方案

核心问题原因

  1. 缓存策略限制了实时数据获取:使用cache-and-network时,Apollo Client会优先返回缓存数据,若网络请求返回的新数据与缓存状态一致(或缓存未及时更新),onCompleted回调可能无法触发;即使数据已更新,也可能因缓存优先级导致回调拿到的仍是旧状态。
  2. 定时器引用存在闭包问题:全局变量timer在组件重新渲染时容易出现引用失效,导致clearInterval无法正确停止定时器,造成查询持续执行。

修复步骤

1. 调整查询的缓存策略

将fetchPolicy改为'network-only',强制每次请求都从网络拉取最新数据,确保onCompleted能获取到实时的进度状态:

const [
  checkProgress,
  { loading2, data2 }
] = useLazyQuery(CHECK_PROGRESS, {
    fetchPolicy: 'network-only', // 替换原cache-and-network策略
    onCompleted: (data) => {
      if(data.progress.completed) {
        setInProgress(false)
        // 你的完成状态逻辑代码
      } else {
        // 你的未完成状态逻辑代码
      }
    }
  }
)

2. 使用useRef管理定时器引用

用useRef替代全局变量存储定时器,避免闭包导致的引用丢失问题,确保定时器能被正确清理:

import { useRef } from 'react';

// 替换原全局timer变量
const timerRef = useRef(null);

useEffect(() => {
  if (inProgress) {
    timerRef.current = setInterval(() => {
      checkProgress()
    }, 1000 * 60)
  } else {
    if(timerRef.current) {
      clearInterval(timerRef.current)
      timerRef.current = null
    }
  }
  // 组件卸载时强制清理定时器
  return () => {
    if(timerRef.current) {
      clearInterval(timerRef.current)
    }
  }
}, [inProgress, checkProgress]) // 添加checkProgress到依赖,避免闭包捕获旧函数引用

3. 兜底方案:监听查询结果变化(可选)

如果担心onCompleted仍有触发异常,可以通过监听data2的变化来处理状态更新,作为额外保障:

useEffect(() => {
  if(data2?.progress?.completed) {
    setInProgress(false)
    // 你的完成状态逻辑代码
  }
}, [data2])

修复后效果

当data.progress.completed变为true时:

  • onCompleted会触发并调用setInProgress(false)
  • useEffect检测到inProgress状态变化,会立即清理定时器,停止后续的进度查询

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:39:15