Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to chain together Mutations in apollo client

I have a bunch of information stored in my state that I need to pass to my graphQL server using mutations, but I need to use the results of each mutation before I call the next one since I need to:

  • Create a new object in my database
  • Use the id generated for that object to create another object
  • Modify the original object to store the id generated by the second object

I noticed that apollo Mutation components have an onCompleted callback, but I don't know how to use this callback to fire off another mutation or whether it's the right way solve my problem. I also looked into batching my mutations to send them all at once but it doesn't seem like that is the solution either. Any help would be appreciated

like image 652
Caleb Nelson Avatar asked Aug 07 '18 00:08

Caleb Nelson


People also ask

What is mutation in Apollo Client?

The useMutation React hook is the primary API for executing mutations in an Apollo application. To execute a mutation, you first call useMutation within a React component and pass it the mutation you want to execute, like so: JavaScript. my-component.jsx.

How do you update Apollo cache after mutation?

If a mutation updates a single existing entity, Apollo Client can automatically update that entity's value in its cache when the mutation returns. To do so, the mutation must return the id of the modified entity, along with the values of the fields that were modified.


2 Answers

As you've mentioned, the unique way to solve it is batching all the mutations, check out the issue related!

Actually, it's not that bad to compose them, you could do something like this:

const handleClick = async (mutation1Fn, mutation2Fn, mutation3Fn) => {
  const data1 = await mutation1Fn()
  const data2 = await mutation2Fn()
  const data3 = await mutation3Fn()
}

const Mutations = () => (
  <Composer
    components={[
      <Mutation mutation={mutation1} />,
      <Mutation mutation={mutation2} />,
      <Mutation mutation={mutation3} />
    ]}
  >
    {([mutation1Fn, mutation2Fn, mutation3Fn]) => (
      <button
        onClick={() => handleClick(mutation1Fn, mutation2Fn, mutation3Fn)}
      >
        exec!
      </button>
    )}
  </Composer>
)

Let me know if you're struggling with something!

like image 140
Carlos Rufo Avatar answered Sep 21 '22 20:09

Carlos Rufo


All you need to do is nest these mutations depending on the data being passed.

The onCompleted and onError props can be used in your case, and they have access to the new data result too. But I personally think a nested format is more readable and easier to debug later.

It would be something like:

const Mutations = () => (
  <Mutation mutation={m1}>
    {(mutation1, { loading, error, data }) => (
       if (loading) return `Loading...`
       if (error) return `Error...`

       const id = get(data, 'result.id')

       return (
          <Mutation mutation={m2} variables={id} />
            {(mutation2, { loading, error, data }) => (

             if (loading) return `Loading...`
             if (error) return `Error...`

             (...)
            )}
          </Mutation>
     )}
  </Mutation>
)
like image 20
morinx Avatar answered Sep 24 '22 20:09

morinx