0

All I want to do is add an item to the items array in my Cart object.

What I am trying to do is simply execute my backend addItem mutation. After that I want to manually update the cache, but for now I am just re-fetching the query because I am unable to even successfully get the query to run.

In this code I am using the pothos withinput plugin: link to docs

I have tried:

  1. Just putting the hardcoded input object into the addItem hook
  2. Listing each Variable out one by one into the addItem hook
  3. Describing the types of each prop in the original gql MUTATION
  4. And passing the hardcoded input into the addItem hook via variables object
  5. Passing hardcoded values into the actual addItem mutation
  6. I have tried inputting the proper typing via a gql tag example below:
    const THE_TYPE = gql`input addItemInput { 
  cartId: String!
  id: String!
  name: String!
  price: Float!
}
`


    const MUTATION = gql`
mutation AddItem($input: ${THE_TYPE}!) {
  addItem(input: $input){carts{
id
items{
name
}}}
`;

*When I run the following mutation in my graphiql interface it works:

mutation MyMutation{
addItem(input:{
  cartId: "2",
  id: "12",
  name: "New Item!",
  price: 1900,
}){
  items{
    name
  }
}}

However when I run the mutation below I get a 400 error:

Error: Response not successful: Received status code 400

import { useQuery, gql, useMutation } from '@apollo/client';

export default function DisplayCarts() {

    interface Cart {
        id: string;
        items: string[];
    }

    interface Items {

    }

    const GET_CARTS = gql`
query {
carts{
id
items{
name
}}} `;



    const MUTATION = gql`
mutation AddItem($input: Any) {
addItem(input: $input){
carts{
id
items{
name
}}
}}`;




    const { loading, error, data } = useQuery(GET_CARTS)

    const [addItem] = useMutation(MUTATION, {

        refetchQueries: [{ query: GET_CARTS }]


        // update(cache, { data: { addItem } }) {
        // addItem is the response of the query of add item function         
        // console.log(data);
        // @ts-ignore
        //     const { carts } = cache.readQuery({ query: GET_CARTS });

        //     cache.writeQuery({
        //         query: GET_CARTS,
        //         data: { carts: [...carts, addItem] }
        //     })
        // }
    })



    function AddTodo() {
        let theInput = {
            cartId: "2",
            id: "12",
            name: "New Item!",
            price: 1900,
            quantity: 2
        }
        // @ts-ignore
        addItem({ variables: { input: theInput } });
    };

Here is my backend resolver function using pothos

Keep in mind my query does work in my graphiql interface so the issue is probably not on the backend

builder.mutationType({
    fields: (t) => ({
        addItem: t.fieldWithInput({
            input: {
                cartId: t.input.string({ required: true }),
                id: t.input.string({ required: true }),
                name: t.input.string({ required: true }),
                price: t.input.int({ required: true }),
                quantity: t.input.int({ required: true, defaultValue: 1 }),
            },
            type: Cart,
            resolve: (_, { input: { cartId, ...input } }) => {
                const cart = CARTS.find((cart) => cart.id === cartId);

                if (!cart) {
                    throw new Error(`Cart with id ${cartId} not found`)
                }

                return {
                    id: cartId,
                    items: [...cart?.items, input]
                }
            }
        }),
    }),
})
Wayne
  • 660
  • 6
  • 16

2 Answers2

1

The problem lies with:

mutation AddItem($input: Any) {
  addItem(input: $input){…}

There is no Any in GraphQL. The 400 is a result of an invalid query/mutation. Note that you're not actually running the same mutation that you are in GraphiQL.

Try using an input type for example in your typeDefs (on the server), add:

input addItemInput { 
  cartId: String!
  id: String!
  name: String!
  price: Float!
}

Then in your client code:

const MUTATION = gql`
  mutation AddItem($input: addItemInput) {
    addItem(input: $input){…}
  }
`
Michel Floyd
  • 18,793
  • 4
  • 24
  • 39
  • Thank you so much for taking the time to try and help a junior dev, I really appreciate it. In your solution should I replace input with type or interface? My code doesn't know that we are defining the type. – Wayne Oct 26 '22 at 18:50
  • See https://graphql.org/graphql-js/mutations-and-input-types/ - `input` is an alternative to type or interface and it's intended for mutations. – Michel Floyd Oct 26 '22 at 18:59
  • I looked at the docs I don't mean to be annoying, but I don't see how I use this stuff on the front end I am using the Apollo client on the front end and pothos on the back end. My backend code works fine I am just having a hard time writing the query on the front end. – Wayne Oct 26 '22 at 19:44
  • It's clear that I don't know what I am doing, but I am trying to learn. And I appreciate any direction you can give me – Wayne Oct 26 '22 at 19:48
  • I am pretty sure the syntax I am using on the backend in the mutation currently does that. I believe this link will explain how it works: https://pothos-graphql.dev/docs/plugins/with-input#install Under Defining fields with inputs it shows an example of the schema that the code produces, I believe I am doing it correctly. – Wayne Oct 26 '22 at 21:52
  • Then are you calling it on the front-end correctly? – Michel Floyd Oct 26 '22 at 22:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/249089/discussion-between-wayne-and-michel-floyd). – Wayne Oct 27 '22 at 00:28
0

Firstly some necessary information:

When using pothos with input plugin it formulates the query type for you following the following rule: ${ParentType.name}${Field.name}Input. I hoghly recomend you follow the link and look at the docs yourself so you can understand exactly how your query should look.

Here is the link to the corresponding docs

The correct query:

    const MUTATION = gql`
  mutation AddItem($input:MutationAddItemInput!) {
    addItem(input: $input){
            items{
                name
            }
        }
    }
`;
  1. If you get a 400 error it is probably your query is just wrong
  2. If you get a weird error with in it check your brackets you might be missing one or two
Wayne
  • 660
  • 6
  • 16