React Apollo - Creating array of Users results in Error: The type of Mutation must be Input Type but got []


#1

I am trying to create a ‘Slack’ type clone using Prisma/Apollo/React but I have run into a brick wall. I am currently trying to create a Direct Message functionality which can be achieved by the user selecting users from a list and subsequently creating the Direct Message group (Conversation) using the users’ IDs.

My datamodel is as follows:

type User {
    id: ID! @unique
    firstname: String!
    lastname: String!
    username: String! @unique
    email: String! @unique
    password: String!
    conversations: [Conversation!]!
}

type Message {
    id: ID! @unique
    text: String!
}

type Conversation {
    id: ID! @unique
    users: [User!]!
}

My schema is as follows:

type Mutation {
    createMessage(text: String!): Message!
    createConversation(users: [User]!): Conversation
    signup(
        email: String!
        password: String!
        firstname: String!
        lastname: String!
        username: String!
    ): User!
    signin(email: String!, password: String!): User!
}

type Query {
    messages(where: MessageWhereInput, orderBy: MessageOrderByInput): [Message]!
    me: User
    users: [User]!
    # messages: [Message]!
}

type Subscription {
    newMessage: Message!
}

type User {
    id: ID!
    email: String!
    firstname: String!
    lastname: String!
    username: String!
    conversations: [Conversation!]!
}

So, in the Playground I can create a conversation through the following code:

mutation {
	createConversation(data: {
    users: {
      connect: [
        {username: "pinksoir"},
        {username: "imginaliu"}
      ]
      }
  }) {
    users {
      username
    }
  }
}

However, I am having difficulty connecting Apollo to the backend. Every time I run the mutation I get the error “Error: The type of Mutation.createConversation(users:) must be Input Type but got: [User]!.” I’m sure that I have the resolver set up incorrectly and also the Apollo side is most likely incorrect too. I’ve read a lot of the docs and cannot figure out how to do this.

My resolver is as follows:

async createConversation(parent, args, ctx, info) {
    const newConversation = await ctx.db.mutation.createConversation(
        {
            data: {
                users: {
                    connect: [{ id: args.userId }]
                }
            }
        },
        info
    );
    return newConversation;
},

And my Apollo stuff is:

const CREATE_CONVERSATION_MUTATION = gql`
    mutation CREATE_CONVERSATION_MUTATION($users: [User]!) {
        createConversation(users: $users) {
            users {
                id
            }
        }
    }
`;

The variables for the mutation are this.state which I have hardcoded to be:

state = {
     users: [{username: "pinksoir"}, {username: "imginaliu"}]
};

I hope someone can point me in the right direction because I’m starting to pull out what little of my hair I have left!

Thanks for any help you can give :raised_hands:


#2

I have found the solution. I shouldn’t have been trying to pass the User as an argument to the createConversation method. It should be the user ID.

datamodel for Conversation:

type Conversation {
    id: ID! @unique
    users: [User!]!
}

schema (mutation):

type Mutation {
    createConversation(users: [ID!]!): Conversation
}

resolver:

async createConversation(parent, { users }, ctx, info) {
    const conversation = await ctx.db.mutation.createConversation(
        {
            data: {
                users: {
                    connect: [...users.map(id => ({ id }))]
                }
            }
        },
        info
    );

    console.log(conversation);

    return conversation;
},

Apollo GraphQL call:

const CREATE_CONVERSATION_MUTATION = gql`
    mutation CREATE_CONVERSATION_MUTATION($users: [ID!]!) {
        createConversation(users: $users) {
            id
        }
    }
`;

Hardcoded state (which will be set programmatically):

state = {
        users: ['cjqp2x7s21d6p0976mkhui0hp']
};

Hope this can be of help to anyone else that might be confused!


#3

You could also pass the prisma created type UserWhereUniqueInput type. Like so:

type Mutation {
    createConversation(users: [UserWhereUniqueInput!]!): Conversation
}

Try it :slight_smile:


#4

Thanks for the tip! So in that case I could use either username, email, or id of the User as they are each unique?


#5

Exactly!

The forum asks that each porst be at least 20 characters so here you go.


#6

Excellent. That’s super useful, thanks! The more I learn Prisma/GraphQL the more I come to love it :slight_smile:


#7

By the way here is how I avoid unnescesarily redefining types:


#8

This topic was automatically closed 45 days after the last reply. New replies are no longer allowed.