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

使用useSWR钩子执行GraphQL Mutation查询时变量传递错误的排查求助

解决useSWR执行MongoDB Atlas Realm GraphQL Mutation时的变量传递问题

看起来你遇到的核心问题是没有正确把变量传递到GraphQL Mutation请求中,而且对useSWR处理Mutation的方式存在一些误解。让我一步步帮你理清问题并解决:

问题根源

  1. useSWR的默认逻辑不适合Mutation:useSWR本质是为数据获取(GET类操作)设计的,默认的fetcher函数不会处理GraphQL Mutation需要的POST请求格式,也不会正确携带变量。
  2. mutate调用方式错误:你传递给mutate的参数没有被解析为GraphQL请求所需的变量结构,导致后端提示$data变量未提供。

解决方案

第一步:创建自定义GraphQL Fetcher函数

首先需要一个专门处理GraphQL查询和Mutation的fetcher,它要包含POST请求、正确的请求体格式,以及MongoDB Realm要求的认证信息。

在项目中新增一个工具文件(比如utils/graphqlFetcher.ts):

import { useContext } from "react";
import { AuthContext } from "../context/AuthContext";

export async function graphqlFetcher(query: string, variables = {}) {
  // 替换成你的MongoDB Atlas Realm GraphQL端点
  const API_URL = "https://realm.mongodb.com/api/client/v2.0/app/[你的APP ID]/graphql";
  
  // 从AuthContext获取用户的access token(根据你的Context结构调整)
  const user = useContext(AuthContext);
  const token = user?.accessToken;

  const res = await fetch(API_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`, // Realm认证必需的请求头
    },
    body: JSON.stringify({
      query,
      variables, // 这里将变量正确传递给GraphQL服务
    }),
  });

  const data = await res.json();
  if (data.errors) {
    throw new Error(data.errors[0].message);
  }
  return data;
}

第二步:修正Mutation的执行方式

useSWR本身更适合数据查询,对于写操作,推荐使用SWR 2.x提供的useSWRMutation钩子(专门处理Mutation),这会让代码更清晰:

方案1:使用useSWRMutation(推荐)

先确保安装了最新版SWR,然后修改你的组件:

// 导入useSWRMutation
import useSWRMutation from 'swr/mutation';
import { graphqlFetcher } from '../utils/graphqlFetcher';

// 替换原来的useSWR(INSERT_TRANSACTION)
const { trigger, isMutating } = useSWRMutation(
  'insert-transaction', // 自定义缓存key,用于标识这个Mutation
  (_, { arg }) => graphqlFetcher(INSERT_TRANSACTION, arg)
);

// 在onFinish里调用trigger执行Mutation
const onFinish = async (values) => {
  const txnData = {
    date: new Date(),
    user_id: userId,
    category: values.category[0],
    subcategory: values.category[1],
    type: values.txntype,
    amount: values.amount,
    description: values.description,
    mode: values.mode,
    account: {
      account_name: "ICICI bank",
      bank_name: "ICICI bank",
      type: "savings",
    },
  };

  try {
    await trigger({ data: txnData });
    console.log("Transaction inserted successfully!");
    setVisible(false);
    // 如果需要刷新其他查询数据,比如交易列表,可以调用对应useSWR的mutate
    // 示例:mutate(TRANSACTION_LIST_QUERY);
  } catch (err) {
    console.error("Error inserting transaction:", err);
  }
};

方案2:直接调用Fetcher(适合老版本SWR)

如果你不想用useSWRMutation,也可以直接在onFinish里调用自定义fetcher,无需借助useSWR的缓存逻辑:

const onFinish = async (values) => {
  const txnData = { /* 构造数据 */ };
  
  try {
    await graphqlFetcher(INSERT_TRANSACTION, { data: txnData });
    console.log("Transaction inserted successfully!");
    setVisible(false);
    // 刷新相关数据
  } catch (err) {
    console.error("Error inserting transaction:", err);
  }
};

第三步:确认认证信息有效性

确保你的AuthContext中包含了用户的accessToken,MongoDB Realm的GraphQL API需要这个令牌来验证用户权限,否则Mutation会被拒绝。如果你的Context只存储了userId,需要调整为存储完整的用户对象(包含accessToken)。

为什么你的代码会报错?

你之前的代码中,useSWR(INSERT_TRANSACTION)只是把Mutation字符串作为缓存key,默认的fetcher会尝试用GET请求去获取这个字符串对应的资源,完全不符合GraphQL Mutation的要求。而调用mutate([INSERT_TRANSACTION, { data: txnData }])时,参数没有被解析为GraphQL需要的变量结构,导致后端接收不到$data变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:27:43