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

Next.js 使用 @apollo/client useQuery 时 data.nodes 偶发 undefined 问题咨询

问题根因和修复方案

被忽略的核心问题

  • 代码执行顺序错误
    useQuery 首次执行时默认处于 loading 状态,此时data值为undefined。你将data.nodes访问语句放在 loading、error 判断之前,相当于直接操作 undefined 的属性,必然抛出错误。你在控制台看到打印的 data 带有 nodes 属性,是浏览器控制台的引用类型打印延迟特性:你点开打印对象的展开箭头时,查询已经返回数据,但打印执行的那一刻 data 确实是空值。热重载时组件复用了之前已经返回的查询结果,所以小概率能拿到有效值。
  • 缺少嵌套属性的兜底处理
    哪怕请求完成,也可能存在查询结果结构不符合预期、参数错误返回空结构的场景,直接访问深层属性容易触发报错。
  • 潜在的查询参数取值时机问题
    如果store.get("ids")是组件渲染后才异步存入的,首次触发 useQuery 时 ids 为空,请求返回的结构自然没有 nodes 属性,后续 ids 变更后如果没有触发重查,也会一直拿不到正确结果。

修复后的代码示例

import { useQuery } from "@apollo/client";
import { Fragment } from "react";

const myComponent = () => {
  const ids = store.get("ids");
  const { loading, error, data } = useQuery(GET_PRODUCTS_BY_ID, {
    variables: { ids: ids },
    // 可选配置:ids为空时不触发无效查询
    skip: !ids?.length,
  });

  // 所有data相关操作必须放在loading、error判断之后
  if (loading) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

  // 用可选链做访问兜底
  console.log(data);
  console.log(data?.nodes);

  // 遍历前兜底为空数组,避免map时报错
  const nodeList = data?.nodes || [];

  return (
    <Fragment>
      {nodeList.map(node => (
        <div key={node.id}>{/* 你的业务渲染逻辑 */}</div>
      ))}
    </Fragment>
  );
};

export default myComponent;

额外校验点

  • 确认GET_PRODUCTS_BY_ID的查询语句里显式声明了返回nodes字段,GraphQL 只会返回你手动指定的字段,漏写的话接口不会返回该属性
  • 如果ids是异步更新的,建议把ids存入组件state,更新state触发组件重渲染,自动触发useQuery重新查询

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 22:33:04