Kevvv
Kevvv

Reputation: 4023

How do I chain useQuery and useMutation in GraphQL properly?

I have useQuery and useMutation from react-apollo-hooks back to back. I want to be able to use the returned values from useQuery as variables for useMutation. Currently, the values from useQuery isn't returned in time for the variables, causing the variables to be undefined.

const { data, error, loading } = useQuery(GET_POSTS, { 
    variables: {
        id: props.match.params.id
    }
})
const item = props.match.params.id
const owner = data.posts[0].author.id
const variables = { item , owner, startDate, endDate }
const bookItem = useMutation(CREATE_BOOKING_MUTATION, variables)

The variable data.posts[0].author.id shows undefined. How do I make sure that the returned value is defined in time?

Upvotes: 3

Views: 8968

Answers (3)

Anis
Anis

Reputation: 11

useMutation when the useQuery is completed like this:

const bookItem = useMutation(CREATE_BOOKING_MUTATION,{
variables:{//your variables},
// to refrech your query after you create mutation
refetchQueries: [
    {
      query: GET_POSTS,
      awaitRefetchQueries: true,
    },
  ]} );   
const { data, error, loading } = useQuery(GET_POSTS, { 
 variables: {
   id: props.match.params.id
  },
    //useMutation when the useQuery is completed
   onCompleted: () => {
   bookItem();
},

})

Upvotes: 0

pjoe
pjoe

Reputation: 326

I think you can pass the variables when you actually call the mutation instead, something like:

...
const bookItem = useMutation(CREATE_BOOKING_MUTATION)
...
if(!loading && !error && data) {
  bookItem({
    variables: {
      owner: data.posts[0].author.id,
      ...
    }
  })
}

Upvotes: -1

xadm
xadm

Reputation: 8418

How do I make sure that the returned value is defined in time?

You can simply check condition after useQuery block


UPDATE

Hooks can't be called conditionally.

Usual advice is to place condition in useEffect:

const { data, error, loading } = useQuery(GET_POSTS, { 
  variables: {
    id: props.match.params.id
  }
})
const item = props.match.params.id

// data.posts can be undefined at start
const owner = loading ? null : data.posts[0].author.id
const variables = { item , owner, startDate, endDate }
const bookItem = useMutation(CREATE_BOOKING_MUTATION, variables)
useEffect(() => {
  if(!loading) {
    bookItem(); // called when data ready
  }
})

Another option: useApolloClient:

  • useQuery to load data needed in mutation

  • const client = useApolloClient();

  • useEffect - conditionally (!loading or data not empty) use client.mutate() with fetched (in query) data as variables;

Custom hook can be done with 3 parameters: (query, mutation, { mapDataToVariables })

Upvotes: 7

Related Questions