How to chain two GraphQL queries in sequence using Apollo Client
Solution 1
The props added by your firstQuery
component will be available to the component below (inside) it, so you can do something like:
export default compose(
graphql(firstQuery, {
name: 'firstQuery'
}),
graphql(secondQuery, {
name: 'secondQuery',
skip: ({ firstQuery }) => !firstQuery.data,
options: ({firstQuery}) => ({
variables: {
var1: firstQuery.data.someQuery.someValue
}
})
})
)(withRouter(TestPage))
Notice that we use skip
to skip the second query unless we actually have data from the first query to work with.
Using the Query Component
If you're using the Query
component, you can also utilize the skip
property, although you also have the option to return something else (like null
or a loading indicator) inside the first render props function:
<Query query={firstQuery}>
{({ data: { someQuery: { someValue } = {} } = {} }) => (
<Query
query={secondQuery}
variables={{var1: someValue}}
skip={someValue === undefined}
>
{({ data: secondQueryData }) => (
// your component here
)}
</Query>
Using the useQuery Hook
You can also use skip
with the useQuery
hook:
const { data: { someQuery: { someValue } = {} } = {} } = useQuery(firstQuery)
const variables = { var1: someValue }
const skip = someValue === undefined
const { data: secondQueryData } = useQuery(secondQuery, { variables, skip })
Mutations
Unlike queries, mutations involve specifically calling a function in order to trigger the request. This function returns a Promise that will resolve with the results of the mutation. That means, when working with mutations, you can simply chain the resulting Promises:
const [doA] = useMutation(MUTATION_A)
const [doB] = useMutation(MUTATION_B)
// elsewhere
const { data: { someValue } } = await doA()
const { data: { someResult } } = await doB({ variables: { someValue } })
Solution 2
For anyone using react apollo hooks the same approach works.
You can use two useQuery
hooks and pass in the result of the first query into the skip
option
of the second,
example code:
const AlertToolbar = ({ alertUid }: AlertToolbarProps) => {
const authenticationToken = useSelectAuthenticationToken()
const { data: data1 } = useQuery<DataResponse>(query, {
skip: !authenticationToken,
variables: {
alertUid,
},
context: makeContext(authenticationToken),
})
const { data: data2, error: error2 } = useQuery<DataResponse2>(query2, {
skip:
!authenticationToken ||
!data1 ||
!data1.alertOverview ||
!data1.alertOverview.deviceId,
variables: {
deviceId:
data1 && data1.alertOverview ? data1.alertOverview.deviceId : null,
},
context: makeContext(authenticationToken),
})
if (error2 || !data2 || !data2.deviceById || !data2.deviceById.id) {
return null
}
const { deviceById: device } = data2
return (
<Toolbar>
...
// do some stuff here with data12
Related videos on Youtube
afterglowlee
Updated on October 26, 2020Comments
-
afterglowlee over 3 years
I am using Apollo Client for the frontend and Graphcool for the backend. There are two queries
firstQuery
andsecondQuery
that I want them to be called in sequence when the page opens. Here is the sample code (the definition of TestPage component is not listed here):export default compose( graphql(firstQuery, { name: 'firstQuery' }), graphql(secondQuery, { name: 'secondQuery' , options: (ownProps) => ({ variables: { var1: *getValueFromFirstQuery* } }) }) )(withRouter(TestPage))
I need to get
var1
insecondQuery
from the result offirstQuery
. How can I do that with Apollo Client and compose? Or is there any other way to do it? Thanks in advance. -
afterglowlee about 6 yearsWork like a charm! Thanks Daniel. It's strange that I didn't find the documentation on this anywhere.
-
Varun Singh over 5 yearsI can't believe this is working. Couldn't find this anywhere else
-
Velidan about 2 yearsThank you @Damian, your post helped me to understand this feature. In my opinion this approach works only for the 2-3 sequenced queues etc., otherwise, the
skip
arguments list will be too long, just like in the answer