Graphql LazyQuery

Hello RW community,

I have a question related to GraphQL and a lazyquery setup. I have posted this question here since there are many GraphQL experts in this community who might be able to share their thoughts.

Here is the code snippet of my lazyquery setup:

import { gql, useLazyQuery } from '@apollo/client'

const GET_GREETING = gql`
  query GetGreeting($language: String!) {
    greeting(language: $language) {
      message
    }
  }
`

export const MainSubmission = () => {
  const [loadGreeting, { called, loading, data }] = useLazyQuery(GET_GREETING)

  const myFunc = async () => {
    loadGreeting({ variables: { language: 'english' } }).then((data) => {
      console.log('data = ', data)
    })
  }

  return (
    <div>
      <button onClick={myFunc}>Load greeting</button>
    </div>
  )
}

The issue is that the above code behaves unpredictably. In localhost env, sometimes(90% of the times) the console section prints the data, and sometimes(10% of the times) it does not. In production environment, it doesn’t work at all btw. When I check the backend, it works fine, and there are no issues.

To troubleshoot the problem, I made a slight change to the above code by moving the console.log into the lazyquery definition section like below:

const [loadGreeting, { called, loading, data }] = useLazyQuery(GET_GREETING, {
  onCompleted: (data) => {
    console.log('data:', data)
  },
})

With this change, the code works without any issue on both localhost and production environment.

My question is, why does the first case not work as expected, but the second case works without issue? The backend is doing just fine in both cases.

Thanks in advance.

Hi @rouzbeh,

[edited, because I misread the code]

I believe the second form is the correct way to chain functions/side-effects from useLazyQuery

I assume Apollo client under the hood will intercept the promises somehow, an only call the onComplete handler when its time to resolve.

Hi @danny thanks. Is the second approach generally advised? Have you seen similar issues?

Yes the second approach is advised you should use the onCompleted and onError function provided by useLazyQuery you can also do other things there like refetchQueries our manually update the cache.

1 Like

Note that in many case you might want to use

const client = useApolloClient()
...
client.query({query: ...})

instead of useLazyQuery
Inparticular if your query is not idempotent, useLazyQuery will return cached values whereas query will behave more like a rest endpoint

1 Like