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

useQuery获取数据后useEffect未触发的问题排查

问题分析与解决方案

从你的日志和代码来看,useQuery已经成功获取到数据,但依赖data的useEffect未触发,无法将数据存入context。下面是具体的原因排查和解决办法:

可能的原因及对应方案

1. React浅比较未识别到data变化

useEffect的依赖数组采用浅比较判断是否触发回调。如果Apollo Client返回的data对象引用未发生变化(比如缓存更新时复用了原对象),React会认为依赖没有更新,跳过useEffect执行。

解决办法:

  • 使用数据中的唯一标识作为依赖(比如data?.game?.id),确保数据更新时依赖值必然变化:
    useEffect(() => {
      if (data) {
        setLobbyData(data);
        console.log('%%%%%%%%Data', data);
      }
    }, [data?.game?.id]);
    
  • 或者自定义深比较的useEffect,替代默认的浅比较:
    import { useEffect, useRef } from 'react';
    import _ from 'lodash'; // 需引入lodash或自行实现深比较
    
    function useDeepCompareEffect(callback: () => void, dependencies: any[]) {
      const ref = useRef<any[]>([]);
      if (!_.isEqual(dependencies, ref.current)) {
        ref.current = [...dependencies];
      }
      useEffect(callback, [ref.current]);
    }
    
    // 使用示例
    useDeepCompareEffect(() => {
      setLobbyData(data);
      console.log('%%%%%%%%Data', data);
    }, [data]);
    

2. 改用useQuery的onCompleted回调更可靠

相比依赖useEffect监听data变化,直接在useQuery的onCompleted回调中处理数据存入context的逻辑,更贴合GraphQL查询的生命周期,避免React渲染机制带来的不确定性。

解决办法:
修改useQuery配置,添加onCompleted回调:

const lobbyDataQuery = useQuery<GetGame, GetGameVariables>(GET_LOBBY_DATA, {
  variables: { gameId: params.id },
  notifyOnNetworkStatusChange: true,
  pollInterval: 5000,
  // 首次查询、轮询更新完成时都会触发
  onCompleted: (newData) => {
    setLobbyData(newData);
    console.log('%%%%%%%%Data', newData);
  },
});

3. 确保解构与依赖的一致性

检查解构的data是否和lobbyDataQuery.data保持同步,避免因变量作用域问题导致依赖失效。可以直接使用lobbyDataQuery.data作为useEffect的依赖:

useEffect(() => {
  const currentData = lobbyDataQuery.data;
  setLobbyData(currentData);
  console.log('%%%%%%%%Data', currentData);
}, [lobbyDataQuery.data]);

4. 移除冗余的轮询启动代码

你在第二个useEffect中调用了lobbyDataQuery.startPolling(5000),但useQuery配置里已经设置了pollInterval: 5000,重复启动轮询可能引发数据更新异常,建议移除冗余代码:

useEffect(() => {
  console.log('{{{{{{{', isFocused, lobbyDataQuery.error);
  if (isFocused) {
    refetch();
    // 已在useQuery配置中设置pollInterval,无需重复调用startPolling
    console.log('XXXXXXXXXXXXsetLobbyData', lobbyDataQuery.data);
    setLobbyData(lobbyDataQuery.data);
  }
}, [isFocused, refetch, lobbyDataQuery.data]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:43:13