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

预取Post文档属性时GraphQL返回null,投票状态不更新

问题排查与修复方案

1. GraphQL类型定义与Resolver返回不匹配(核心原因)

你的getVote Query在typeDef里声明返回Post类型,但Resolver实际返回的是post.vote(投票对象)。而前端GET_VOTE查询的是getVote { vote },相当于从返回的Vote对象里再取vote字段,自然会得到null。

修复:

  • 补充Vote类型定义,并修改Query返回类型:
type Vote {
  up: [String]
  down: [String]
}

type Query {
  getVote(postId: String): Vote
}
  • 前端调整GET_VOTE查询,直接获取Vote对象的字段:
export const GET_VOTE = gql`
query GetVote($postId: String){
  getVote(postId: $postId){
    up
    down
  }
}
`;

2. 前端未通过useQuery获取投票数据

组件中使用了voteData但没有对应的useQuery调用,导致无法获取和渲染最新的投票状态。

修复:
在组件中添加useQuery获取投票数据:

import { useQuery, useMutation } from '@apollo/client';
// ...其他导入

export default function Component({ post }: ICardInfo) {
  const [postVote] = useMutation(POST_VOTE);
  // 添加useQuery获取投票数据
  const { data: voteData, refetch } = useQuery(GET_VOTE, {
    variables: { postId: post._id },
  });

  function voteHandler(
    event: React.MouseEvent<HTMLButtonElement>,
    postId: string | undefined
  ) {
    const buttonName = event.currentTarget.name;
    postVote({
      variables: {
        postId: postId,
        userId: session.data?.user._id,
        upDown: buttonName
      },
      onCompleted: () => refetch(), // 手动触发重取更新数据
      onError: (err) => console.error(err)
    });
  }

  return (
    <>
      <div className="flex flex-col">
        <button name="up" onClick={(e) => voteHandler(e, post._id)}>
          <ChevronUpIcon className="w-5" />
        </button>
        <h3 className="text-center">{voteData?.getVote?.up.length || 0}</h3>
        <button name="down" onClick={(e) => voteHandler(e, post._id)}>
          <ChevronDownIcon />
        </button>
      </div>
    </>
  );
}

3. GraphQL语法错误(参数缺失逗号)

你的typeDef和POST_VOTE mutation里的参数之间都缺少逗号,会导致GraphQL解析失败:

  • typeDef里的Mutation:userId: String upDown: String 改为 userId: String, upDown: String
  • POST_VOTE gql里的变量:$userId: String $upDown: String 改为 $userId: String, $upDown: String

修复后的typeDef:

type Mutation {
  postVote(postId: String, userId: String, upDown: String): String
}

修复后的POST_VOTE:

export const POST_VOTE = gql`
  mutation postVote($postId: String, $userId: String, $upDown: String) {
    postVote(postId: $postId, userId: $userId, upDown: $upDown)
  }
`;

4. Resolver冗余逻辑优化

Mutation里重复调用await post.save(),且未处理用户重复投票的情况,可优化:

Mutation: {
  postVote: async (parent, args) => {
    try {
      const { postId, userId, upDown } = args;
      await connectDB();
      const post = await Post.findById(postId);
      if (!post) throw new Error("Post not found");

      // 先移除用户在对立投票数组中的记录
      if (upDown === "up") {
        post.vote.down = post.vote.down.filter(id => id !== userId);
        // 避免重复添加
        if (!post.vote.up.includes(userId)) {
          post.vote.up.push(userId);
        }
      } else if (upDown === "down") {
        post.vote.up = post.vote.up.filter(id => id !== userId);
        if (!post.vote.down.includes(userId)) {
          post.vote.down.push(userId);
        }
      }

      await post.save();
      return "Vote updated successfully";
    } catch (err) {
      console.log(err.message);
      throw err; // 抛出错误让前端捕获处理
    }
  },
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:15:04