问题
In my nodejs application
here is my schema.js file
import {
GraphQLBoolean,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} from 'graphql';
import {
connectionArgs,
connectionDefinitions,
connectionFromArray,
connectionFromPromisedArray,
cursorForObjectInConnection,
fromGlobalId,
globalIdField,
mutationWithClientMutationId,
nodeDefinitions,
toGlobalId,
} from 'graphql-relay';
import {
User,
getUser,
getPosts,
createpost,
} from '../data/database.js';
var { nodeInterface, nodeField } = nodeDefinitions(
(globalId) => {
var { type, id } = fromGlobalId(globalId);
if (type === 'User') {
return getUser(id);
}else if (type === 'Post') {
return getPosts(id);
}
return null;
},
(obj) => {
if (obj instanceof User) {
return userType;
}else if (obj instanceof Post) {
return postType;
}
return null;
}
);
var userProfileImageType = new GraphQLObjectType({
name: 'ProfileImage',
fields: {
full: {
type: GraphQLString
}
}
});
var userLocalAccountType = new GraphQLObjectType({
name: 'Local',
fields: {
email: {
type: GraphQLString
}
}
});
var userFacebookAccountType = new GraphQLObjectType({
name: 'Facebook',
fields: {
id: {
type: GraphQLString
},
displayName: {
type: GraphQLString
}
}
});
var userGoogleAccountType = new GraphQLObjectType({
name: 'Google',
fields: {
id: {
type: GraphQLString
},
displayName: {
type: GraphQLString
}
}
});
var postType = new GraphQLObjectType({
name: 'Post',
fields: {
id: globalIdField('Post'),
title: {
type: GraphQLString
},
userId: globalIdField('User'),
content: {
type: GraphQLString
}
},
interfaces: [nodeInterface]
});
/**
* Define your own connection types here
*/
const {
connectionType: postConnection,
edgeType: postEdge,
} = connectionDefinitions({name: 'Post', nodeType: postType});
let createPostMutation = mutationWithClientMutationId({
name: 'CreatePost',
inputFields: {
title: { type: new GraphQLNonNull(GraphQLString) },
content: { type: new GraphQLNonNull(GraphQLString) },
userId: { type: new GraphQLNonNull(GraphQLString) },
},
outputFields: {
postEdge: {
type: postConnection,
resolve: (obj) => ({ node: obj, cursor: obj.insertedId })
},
},
mutateAndGetPayload: ({title, content,userId}) => {
console.log({title, content,userId})
return createpost({title, content,userId})
}
});
var userType = new GraphQLObjectType({
name: 'User',
fields: {
id: globalIdField('User'),
fullName: {
type: GraphQLString,
description: "Users' Full Name"
},
isPremium: {
type: GraphQLBoolean,
description: "Does the user have premium subscription?"
},
currentPostCount: {
type: GraphQLInt,
description: "User's current total post"
},
images: {
type: userProfileImageType,
description: "User's profile image links"
},
local: {
type: userLocalAccountType,
description: "User's local account info"
},
facebook: {
type: userFacebookAccountType,
description: "User's Facebook account info"
},
google: {
type: userGoogleAccountType,
description: "User's Google Plus account info"
},
posts: {
type: postConnection,
args: {
...connectionArgs,
query: { type: GraphQLString }
},
resolve: (rootValue) => {
return connectionFromPromisedArray(getPosts(rootValue))
}
},
},
interfaces: [nodeInterface]
});
var Root = new GraphQLObjectType({
name: 'Root',
fields: () => ({
user: {
type: userType,
resolve: (rootValue, _) => {
return getUser(rootValue)
}
},
})
})
export var schema = new GraphQLSchema({
query: Root,
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
createPost: createPostMutation
})
})
});
and below is my database.js
import User from './models/userModel'
import Post from './models/postModel'
export { User }
export { Post }
export function getUser(user) {
let validUser = false
if (user.local || user.facebook || user.google) {
validUser = true
}
return new Promise((resolve, reject) => {
if (validUser) {
let localEmail = user.local.email || ""
let googleID = user.google.id || ""
let facebookID = user.facebook.id || ""
User.findOne({
$or: [
{ "local.email": localEmail },
{ "facebook.id": facebookID },
{ "google.id": googleID }
]
}, function(err, existingUser) {
if (err || !existingUser) {
resolve({})
} else {
resolve(existingUser)
}
});
} else {
resolve({})
}
})
}
export function getPosts(user) {
return new Promise((resolve, reject) => {
Post.find({}).exec({}, function(err, posts) {
resolve(posts)
});
})
}
export function createpost({title, content,userId}){
return new Promise((resolve, reject) => {
const blogPostModel = new Post({title, content,userId});
const newBlogPost = blogPostModel.save();
if (!newBlogPost) {
throw new Error('Error adding new blog post');
}
resolve({})
})
}
I am getting user by
Relay.QL `query { user}`
I want to fetch all posts along with user
Relay.QL 'query{
user {
id,
posts(first: 3) {
edges {
node {
id,
title
}
}
}
}
}'
but i am getting below error in terminal
Failed to execute query `UserQueries` for the following reasons:
1. Cannot read property 'after' of undefined
le {id,displayName},_posts3KBCho:posts(first:3) {edges {node
Please help. Thanks in Advance.
回答1:
Update #1:
The problem is in the implementation of posts
field in userType
definition.
posts: {
type: postConnection,
args: {
...connectionArgs,
query: { type: GraphQLString }
},
resolve: (rootValue) => {
return connectionFromPromisedArray(getPosts(rootValue))
}
},
While destructuring args
, the Rest parameter connectionArgs
should come in the end. query
should come first. Because of the wrong use of rest parameters, connectionArgs
is found undefined
.
By the way, you don't pass query
for posts. If you don't provide query
argument, you should just use args: {...connectionArgs},
.
Looks like you've used Mongoose library. If that's the case, one obvious problem is in the implementation of getPosts
function. exec
itself returns a promise. So, it doesn't need to be wrapped in a Promise. Replace this
export function getPosts(user) {
return new Promise((resolve, reject) => {
Post.find({}).exec({}, function(err, posts) {
resolve(posts)
});
})
}
with this
export function getPosts(user) {
return Post.find({user_id: user._id}).exec();
}
Please let me know if you face further problems after fixing this.
回答2:
Made the same mistake today and it took me little bit to find right solution. I looked at your question with same issue, but didn't resolved my problem. After some time I've noticed I'm missing args
in my connectionFromPromisedArray
call. So to fix your issue try changing this:
posts: {
type: postConnection,
args: {
...connectionArgs,
query: { type: GraphQLString }
},
resolve: (rootValue, args) => { // <== here is added args attribute
return connectionFromPromisedArray(getPosts(rootValue), args) // <== here is added args attribute
}
},
来源:https://stackoverflow.com/questions/38540767/cannot-read-property-after-of-undefined-in-implementing-react-relay