I have a backend made with Express / Apollo Server / GraphQL / MongoDB / Mongoose and a frontend made with React.
I have my component where I want to do mutations and queries, I checked the connection between frontend and backend and it's good.
My mutation on backend:
createUser(input: SignupInput!): AuthUser!
input SignupInput {
name: String!
username: String!
email: String!
password: String!
}
The AuthUser return is an User! that has more fields but I think it's not necessary info.
On my frontend
const NEW_USER = gql`
mutation CreateUser($type: SignupInput!) {
createUser(input: $type) {
user {
id
}
}
}
`;
const [newTest, { data }] = useMutation(NEW_USER);
const onSubmit = (formData) => {
newTest({
variables: {
name: formData.name,
username: formData.username,
email: formData.email,
password: formData.password,
},
});
};
The network response for error 400:
"Variable \"$type\" of required type \"SignupInput!\" was not provided."
I don't really understand why this is happening, I've seen in other people's code that creating the variable with the name of the input type you have on the backend works.
If I try to destructure the SignInput! type and write {$name: !String, ...) I get this error:
Unknown argument \"name\" on field \"Mutation.createUser\".", locations: […], extensions: {…} }
newTest({
variables: {
input: {
name: formData.name,
username: formData.username,
email: formData.email,
password: formData.password,
}
},
});
Input was not passed in the mutation function.
Related
I have an Apollo GraphQL projects where I have created my own Query and Mutations. I have done using mock data and Query and Mutation works fine. But when I am trying to do with Sequelize ORM, I am getting the error
"TypeError: Cannot read property 'getListings' of undefined",
" at listings (/home/ayman/Desktop/apollo-graphql/graphql-app/functions/graphql.js:50:19)",
" at field.resolve (/home/ayman/Desktop/apollo-graphql/graphql-app/node_modules/graphql-extensions/dist/index.js:134:26)"
Query and Mutations in graphql.js:
const { ApolloServer, gql} = require("apollo-server-lambda");
const { Listing, User } = require("../db");
const jwt = require("jsonwebtoken");
const typeDefs = gql`
type Query {
listings: [Listing!]!
}
type Mutation {
createListing(input: CreateListingInput!): Listing!
}
input CreateListingInput {
title: String!
description: String
url: String!
notes: String
}
type Contact {
id: ID!
name: String!
company: Company
email: String
notes: String
}
type Company {
id: ID!
name: String!
logo: String
listings: [Listing!]!
url: String
}
type Listing {
id: ID!
title: String!
description: String
url: String!
notes: String
company: Company
contacts: [Contact!]!
}
`;
const resolvers = {
Query: {
listings(_, __, { user }) {
return user.getListings();
},
},
Mutation: {
createListing(_, { input }, { user }) {
return Listing.create({ ...input, userId: user.id });
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
exports.handler = server.createHandler();
I have Sequilize along with Postgres database:
db.js
const Sequelize = require("sequelize");
const sequelize = new Sequelize(process.env.DB_CONNECTION_STRING, {
dialect: "pg",
dialectModule: require('pg'),
dialectOptions: {
ssl: true,
},
});
class User extends Sequelize.Model {}
User.init(
{
email: Sequelize.STRING,
password: Sequelize.STRING,
},
{
sequelize,
modelName: "user",
}
);
class Listing extends Sequelize.Model {}
Listing.init(
{
title: Sequelize.STRING,
description: Sequelize.TEXT,
url: Sequelize.STRING,
notes: Sequelize.TEXT,
},
{
sequelize,
modelName: "listing",
}
);
Listing.belongsTo(User);
User.hasMany(Listing);
exports.sequelize = sequelize;
exports.User = User;
exports.Listing = Listing;
Github Link
Run using netlify dev
Go to URL: http://localhost:8888/.netlify/functions/graphql
Sample GraphQL query
{
listings {
id
title
description
url
company {
name
url
}
}
}
return user.getListings();
you probably mean User, because user is undefined
I see, you are trying to access user object from context. Please check the context definition. It should return an object containing user object explicitly.
I'm building an event managing database that handles RSVPs and links those RSVPs to a specific event. I'm using React, Apollo, GraphQL and Prisma as my stack and am having trouble correctly writing a mutation that would link an RSVP to an existing event. Still relatively new to the syntax, but I can't grab the event.id when I'm using the createRsvp mutation.
I'm able to pass the event.id down on the front-end through props, and I think a less-elegant way of receiving event.id in the args of the RSVP would be creating a hidden form with the event.id, but I KNOW there's got to be a way through graphQL. I've tried looking through the docs and various examples on grabbing the id from a different object. Any help is much appreciated :)
On the backend, here's my datamodel:
type Rsvp {
id: ID! #id
event: Event! #relation(link: INLINE)
firstName: String!
lastName: String!
email: String! #unique
company: String
jobTitle: String
mobile: String
dietary: String
}
type Event {
id: ID! #id
isPublished: Boolean
title: String!
startDate: String!
endDate: String!
description: String!
image: String
address: String
url: String!
suburb: String
postcode: String
state: String
country: String
guestLimit: Int
rsvps: [Rsvp]
}
The actual resolver for the Mutation.. I think I'm incorrectly retrieving the event.id here. My though process is that data: {...args} is first taking in the data from the RSVP form, and the connection to event is linking it to a certain event.
async createRsvp(parent, args, ctx, info) {
// 1. Query the event that is being registered for
const eventId = ctx.request.event.id;
// 2. Create the RSVP for this specific event
const rsvp = await ctx.db.mutation.createRsvp(
{
data: {
...args,
event: {
connect: { id: eventId }
}
}
},
info
);
console.log(rsvp);
return rsvp;
}
};
On the front end, this is what my Mutation looks like
const RSVP_MUTATION = gql`
mutation RSVP_MUTATION(
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
`;
and finally, the Mutation function in the form:
<Mutation mutation={RSVP_MUTATION} variables={({ id }, this.state)}>
{(createRsvp, { loading, error }) => (
<Form
onSubmit={async e => {
e.preventDefault();
const res = await createRsvp();
}}>
The error I receive in the console is "Uncaught (in promise) Error: GraphQL error: Cannot read property 'id' of undefined" which leads me to believe I'm incorrectly trying to access the event.id. Any tips or advice? Thanks again!
Divide and conquer
You can use /graphiql playground to test queries and mutations (API generally).
Testing this mutation:
mutation RSVP_MUTATION(
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
... with required variables you should quickly notice that you need to pass event id as variable, too. No special (more/less elegant), separate method required, this is a standard, query/mutation and variables, nothing more!!!
Just add eventId variable:
mutation RSVP_MUTATION(
$eventId: ID!
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
eventId: $eventId
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
Of course in resolver you'll get it within args, you can use f.e.
const { eventId, ...rest } = args;
const rsvp = await ctx.db.mutation.createRsvp(
{
data: {
...rest,
event: {
React variables can be passed f.e. by
variables={{ eventId: id, ...this.state }}
I have a React client-side project and a Node.js/GraphQL api in two separate repo's.
In my React app, I want to pass an object as variable type into my mutation. Here's how my mutation looks like:
export const CREATE_SPEAKER = gql`
input Expertise {
title: String!
domain: String!
}
mutation CreateSpeaker(
$name: String!
$age: String!
$nationality: String!
$avatar: String!
$expertise: Expertise!
) {
createSpeaker(
speakerInput: {
name: $name
age: $age
nationality: $nationality
avatar: $avatar
expertise: $expertise
}
) {
name
age
nationality
avatar
expertise {
title
domain
}
}
}
`;
In my Node.js project I have the following schema:
input SpeakerInput {
name: String!
age: String!
expertise: ExpertiseInput!
nationality: String!
avatar: String
}
input ExpertiseInput {
title: String!
domain: String!
}
And my resolver:
createSpeaker: async args => {
const { name, age, nationality, avatar, expertise } = args.speakerInput;
const newSpeaker = new Speaker({
name,
age,
nationality,
avatar,
expertise: {
title: expertise.title,
domain: expertise.domain
}
});
try {
return await newSpeaker.save();
} catch (error) {
throw ("Failed to create speaker:: ", error);
}
}
But I'm getting the following error when trying to create the speaker:
Uncaught (in promise) Invariant Violation: Schema type definitions not
allowed in queries. Found: "InputObjectTypeDefinition"
Any suggestions/ideas how to do this?
You can't define additional types when sending requests to a GraphQL service and you don't need to -- just use the types you've already defined on the server (in this case ExpertiseInput:
$expertise: ExpertiseInput!
However, there's no need to use this many variables in the first place:
mutation CreateSpeaker($input: SpeakerInput!) {
createSpeaker(speakerInput: $input) {
name
age
nationality
avatar
expertise {
title
domain
}
}
}
My mongo db data:
{
username: 'gemmi',
age: 14,
id: 'xsxsxsxsxss'
}
type Query:
{
type Query {
getUser(id: String, username: String): User
}
}
resolver
getUser(root, args) {
return Meteor.users.findOne({ _id: args.id, username: args.username });
},
My question is how I can get user by given variable?
So it should return user when i type:
getUser(id: "xsxsxsxsxss", username:"gemmi") { username _id }
and also when I type:
getUser(username:"gemmi") { username _id }
You could replace the id with _id in the Query
{
type Query {
getUser(_id: String, username: String): User
}
}
And then you could simply use the args parameter to perform findOne call
getUser(root, args) {
return Meteor.users.findOne(args);
}
The args object depends on how you performed the query call. You should remember about replacing id with _id in your calls. In the first case, when you did getUser(_id: "xsxsxsxsxss", username:"gemmi"), then args object is { _id: 'xsxsxsxsxss', username: 'gemmi' }, however in second case, when you want to use getUser(username:"gemmi"), the args object is { username: 'gemmi' }, so in both cases you can use it as a query lookup in the findOne method call.
I suggest you add a input type for your query. And let meteor search for the respective user.
It could look like this:
Query:
`
type User {
id: ID!
username: String!
}
input UserInput {
id: ID
username: String
}
type Query {
getUser(user: UserInput!): User!
}
`
Resolver:
...
getUser(root, { user }) {
return Meteor.users.findOne(user);
}
...
This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
Trying to make my first graphQL server, here's what I have written so far.
https://gist.github.com/tharakabimal/7f2947e805e69f67af2b633268db0406
Following error pops up on GraphQL when I try to filter the users by username.
Error on GraphQL
The error occurs in the users field in UserQueriesQL.js.
Is there anything wrong the way I pass arguments on the resolve functions?
user: {
type: UserType,
args: {
username: {
name: 'username',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: function(parentValue, args) {
return User.find( args ).exec();
}
As I am beginner into GraphQL, even I ran into this issue. After going through each file individually I found that I forgot to import into my resolvers
import User from './User';
**import Post from './Post';**
const resolvers = [User, **Posts**];
Maybe this will help!
user: {
type: UserType,
args: {
username: { type: new GraphQLNonNull(GraphQLString) }
},
resolve: function(parentValue, args) {
return User.find( args ).exec(); // User.find({username: 'some name'}).exec();
// will work as matches your mongoose schema
}
Previously, in the args you are providing an an object with nested object username so,
args: { // this won't match your mongoose schema field as it's nested object
username: {
name: 'username',
type: new GraphQLNonNull(GraphQLString)
}
}
so when the user queries and provides args then
your args would be { username: { name: 'abcd' } }
// args = {username: {name: 'abcd'}}
and resolve() is executing User.find({username: {name: 'abcd'}}).exec();
/* searching for username{} object, but
your mongoose schema is username: String */
which doesn't match your database fields, which will always return an empty array [],also which will not match your GraphQL field type, as it is GraphQLNonNull
after viewing the gist the problem is with rootquery
the problem is with rootquery
let RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
users: { type:UserQueries.users, resolve: UserQueries.users }
user: { type: UserQueries.user, resolve: UserQueries.user }
})
});