React-admin无法显示ReferenceField问题(GraphQL/Mongoose/Apollo-server)
解决GraphQL输入类型报错及前端显示用户名问题
核心问题原因
GraphQL中对象类型(比如User)不能直接用在输入类型(Input Type)里,你遇到的Error: The type of MessageInput.username must be Input Type but got: User就是违反了这个规则。输入类型仅支持标量类型(String、Int等)或自定义输入类型,无法引用对象类型。
分步解决方案
1. 调整GraphQL Schema定义
- 保留
Message对象类型的createdBy为User类型,用于查询时返回完整用户信息; MessageInput输入类型的createdBy仍用String类型(对应Mongoose的ObjectId字符串形式),用于创建/更新消息时传递用户ID。
示例代码:
# 定义User对象类型 type User { id: ID! username: String! # 其他用户字段... } # 定义Message对象类型 type Message { id: ID! content: String! createdBy: User! # 查询时返回完整User对象 createdAt: String! } # 定义Message输入类型(用于创建/更新操作) input MessageInput { content: String! createdBy: String! # 传递用户ID的字符串形式 } # 查询与突变定义 type Query { messages: [Message!]! message(id: ID!): Message } type Mutation { createMessage(input: MessageInput!): Message! # 其他突变操作... }
2. 保持Mongoose模型的正确关联
继续使用Schema.Types.ObjectId关联User模型,确保数据库层面的关联逻辑正确:
// models/Message.js const mongoose = require('mongoose'); const Schema = mongoose.Schema; const messageSchema = new Schema({ content: { type: String, required: true }, createdBy: { type: Schema.Types.ObjectId, ref: 'User', // 关联User模型 required: true }, createdAt: { type: Date, default: Date.now } }); module.exports = mongoose.model('Message', messageSchema);
3. 添加GraphQL解析器关联用户数据
在Message对象类型的createdBy字段添加解析逻辑,通过存储的ObjectId查询对应的User文档,返回完整用户信息:
// resolvers/index.js const Message = require('../models/Message'); const User = require('../models/User'); const resolvers = { Query: { async messages() { // 用Mongoose populate预加载关联的用户数据 return await Message.find().populate('createdBy'); }, async message(_, { id }) { return await Message.findById(id).populate('createdBy'); } }, Mutation: { async createMessage(_, { input }) { const newMessage = new Message(input); await newMessage.save(); // 保存后返回带用户数据的消息 return await Message.findById(newMessage._id).populate('createdBy'); } }, // 若populate不够灵活,可手动解析createdBy字段 Message: { async createdBy(parent) { return await User.findById(parent.createdBy); } } }; module.exports = resolvers;
4. React-admin前端显示用户名
在React-admin的Message资源配置中,通过点语法直接访问嵌套的用户名字段:
// src/resources/Message.js import { List, Datagrid, TextField, DateField } from 'react-admin'; export const MessageList = () => ( <List> <Datagrid> <TextField source="id" /> <TextField source="content" /> <TextField source="createdBy.username" label="Created By" /> {/* 直接显示用户名 */} <DateField source="createdAt" /> </Datagrid> </List> );
关键说明
- 输入类型与对象类型的区分是GraphQL的核心规则,必须严格遵守;
- Mongoose的
populate方法可简化关联数据查询,也可通过Resolver手动实现关联查询; - React-admin支持通过点语法访问嵌套字段,直接展示关联对象的属性。
内容的提问来源于stack exchange,提问作者Zovitch
相关产品推荐
相关产品推荐

