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

如何将useEffect获取的数据作为参数传入useQuery的variables?

问题根源

你的错误触发原因和方案缺陷主要来自两个核心问题:

  1. 违反React Hook调用规则:将useQuery放在if (profileTypeA)条件块内,Hook调用顺序必须在组件顶层保持稳定,嵌套在条件/循环内会引发不可预期的bug,这也是你把useQuery移出条件块后错误依然存在的原因之一。
  2. 未控制useQuery的执行时机:useEffect的执行时机晚于组件首次渲染,首次渲染时useQuery就会默认发起请求,此时user还是初始空对象,variables传入的id为undefined,自然会触发参数错误的回调。

最优解决方案

useQuery提供了**enabled配置项**,专门用于控制查询的触发时机,只要enabled值为false,查询就不会发起,完美适配动态参数的场景,不需要手动维护多余的状态和请求判断。

最小改动方案(保留现有useEffect逻辑)

修正后的代码如下:

const router = useRouter();
const { id } = router.query;
// 初始值设为null更容易判断是否已加载到用户数据
const [user, setUser] = useState(null);
const [profileTypeA, setProfileTypeA] = useState(false);

// 1. 把useQuery移到组件顶层,不要放在条件块内
const { loading: queryLoading, error: queryError, data: queryData } = useQuery(
  QUERY_FOR_USER_TYPE_A, 
  {
    variables: { id: user?.userId },
    // 2. 只有满足两个条件才发起查询:是A类型用户 + 用户ID已存在
    enabled: profileTypeA && !!user?.userId,
  }
);
const userData = queryData?.moreData;

useEffect(() => {
  async function getUser() {
    if (!router.isReady) return;
    const userDb = await getUserFromDb(id);
    if (!userDb) {
      return <Error statusCode={404} />;
    }
    const userPayload = userDb.data.payload;
    setUser(userPayload);
    if (userPayload.type === 'A') setProfileTypeA(true);
  }
  getUser();
  return () => {
    consola.success('Cleanup profile page');
  };
// 注意:要把id加入依赖数组,id变化时会重新获取用户数据
}, [router.isReady, id]);

// 渲染逻辑处理
if (!router.isReady || !user) return null;
if (profileTypeA) {
  if (queryLoading) return null;
  if (queryError) return <Error statusCode={404} />;
}
// 后续你的页面渲染逻辑

更简洁的优化方案

你的getUserFromDb请求本身也可以用useQuery实现,不需要手动写useEffect维护状态,逻辑更统一:

const router = useRouter();
const { id } = router.query;

// 第一个查询:获取基础用户数据
const { data: userDb, loading: userLoading, error: userError } = useQuery(
  ['user', id],
  () => getUserFromDb(id),
  {
    // router准备好且id存在时才发起请求
    enabled: router.isReady && !!id,
  }
);
const user = userDb?.data?.payload;
const profileTypeA = user?.type === 'A';

// 第二个查询:获取A类型用户的额外数据
const { loading: queryLoading, error: queryError, data: queryData } = useQuery(
  QUERY_FOR_USER_TYPE_A, 
  {
    variables: { id: user?.userId },
    enabled: profileTypeA && !!user?.userId,
  }
);
const userData = queryData?.moreData;

// 统一处理加载和错误状态
if (userLoading) return null;
if (userError || !user) return <Error statusCode={404} />;
if (profileTypeA) {
  if (queryLoading) return null;
  if (queryError) return <Error statusCode={404} />;
}
// 后续你的页面渲染逻辑

方案说明

enabled配置是React Query官方推荐的动态参数/依赖查询的标准实现,不会发起无效请求,也不会触发不必要的错误回调,完全符合你的预期逻辑:

  1. 先等待用户基础数据加载完成,判断用户类型
  2. 条件满足时自动触发第二个查询,传入正确的用户ID参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:24:08