预取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
相关产品推荐
相关产品推荐

