Search code examples
reactjsgraphqlexpress-graphql

GraphQL Mutation and Query: Cannot read property of undefined


I'm following along a tutorial and have a simple setup using express-graphql. I have a mutation to create a Friend object and a Query to return the same. Auto-complete and schema detection work fine at GraphiQL running at localhost:8080/graphql. I tried searching for similar errors on SO but those either have convoluted examples or are using Apollo.

Here's the GraphQL Mutation I'm trying to execute:

mutation {
  createFriend(input: {
    firstName:"FName1",
    lastName:"LName1",
    email:"[email protected]"
  }) {
    id
  }
}

and the error I see (only the relevant portion of error is shown):

{
  "errors": [
    {
      "message": "Cannot read property 'input' of undefined",
// Erased irrelevant portion of error
}

Here's my schema.js file that's importing resolvers from resolvers.js and makes use of makeExecutableSchema:

import { resolvers } from './resolvers';
import { makeExecutableSchema } from '@graphql-tools/schema';

const typeDefs = `
    type Friend {
        id: ID
        firstName: String
        lastName: String
        age: Int
        email: String
    }

    type Query {
        getFriend(id: ID): Friend
    }

    input FriendInput {
        id: ID
        firstName: String!
        lastName: String
        age: Int
        email: String
    }

    type Mutation {
        createFriend(input: FriendInput): Friend
    }
`;

export const schema = makeExecutableSchema({ typeDefs, resolvers});

Since I'm just exploring graphQL and react, I've been saving Friend objects in an array as shown here in my resolver.js file:

class Friend {
    constructor(id, { firstName, lastName, gender, age, language, email, contacts }) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.age = age;
        this.language = language;
        this.email = email;
        this.contacts = contacts;
    }
}

const friendDatabase = {};

// resolver map
export const resolvers = {
    Query: {
        getFriend: ({ id }) => {
            return new Friend(id, friendDatabase[id]);
        },
    },
    Mutation: {
        createFriend: ({ input }) => {
            let id = require('crypto').randomBytes(10).toString('hex');
            friendDatabase[id] = input;
            return new Friend(id, input);
        },
    },
};

Finally, here's the index.js file that ties everything together:

import express from 'express';
const { graphqlHTTP } = require('express-graphql');
import {schema} from './schema';

const app = express();

app.get('/', (req, res) => {
    res.send('GraphQL is amazing!');
});

app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: true,
}));

app.listen(8080, () => console.log('Running server on port localhost:8080/graphql'));

I've found that the tutorial has been using some out-dated libraries (graphql-tools instead of @graphql-tools/schema) which were pointed out to me by npm logs. I've been updating the code as I followed along but am unable to debug this error.

Any pointers will be appreciated.

EDIT Based off comment from @Viet, to use this:

mutation {
  createFriend({
    firstName:"FName1",
    lastName:"LName1",
    email:"[email protected]"
  }) {
    id
  }
}

I now get this error:

{
  "errors": [
    {
      "message": "Syntax Error: Expected Name, found \"{\".",
// Removed extra lines
    }
  ]
}

Solution

  • Thanks to @xadm's comment, I got it to work. Looking at the query resolvers documentation here, the createFriend mutation signature looks like so:

    createFriend: (parent, {input}, context, info) => {//Do something}
    

    In my initial post, I was only providing this:

    createFriend: ({input}) => {//Do something}
    

    Since I'm not really interested in passing the parent argument, all I needed to do was this:

    createFriend: (_, {input}) => {//Do something}
    

    Making the above change worked without editing my mutation query or any other files. Hope others find this useful.