Ask questionsuseLazyQuery execution function should return a promise

People don't know if they should use a query or a mutation to login an user when that login performs no side-effect (ie, just query for an auth token).

But Apollo users tend to currently use mutations because they want the operation to execute only after user press a submit button.

Recently a new useLazyQuery was added (by @FredyC I think?), and it could be useful to solve this problem: keep a query, but actually execute it after user press a button.

Unlike mutations, it does not return a promise when executed.

I suggest the following should be possible:


edit: actually the screenshot is wrong but you probably understand the point of returning a promise instead of void here (at least in TS typings)

Note other apis do return a promise when called (see "refetch" for example). I think useLazyQuery should follow the exact same convention and not return void.


Answer questions FredyC

And I just came to a realization that the Promise should not be rejected at all. Mainly because it's usually redundant as an error will appear in the result itself and can be handled more gracefully in a render phase. The rejected promise is impossible to be caught by any React mechanism (error boundary) and would need to be handled per each case on the call site, otherwise, the annoying unhandledRejection would appear in logs.

In my opinion, it's enough if the Promise resolves with the whole result object when "loading" is done.

Perhaps that's something to consider for a real implementation later.

export function useLazyQuery<TData = any, TVariables = OperationVariables>(
  query: DocumentNode,
  options?: LazyQueryHookOptions<TData, TVariables>,
): LazyQueryHookTuple<TData, TVariables> {
  const [execute, result] = Hooks.useLazyQuery<TData, TVariables>(query, options)

  const resolveRef = React.useRef<
    (value?: LazyQueryResult<TData>| PromiseLike<LazyQueryResult<TData>>) => void

  React.useEffect(() => {
    if (result.called && !result.loading && resolveRef.current) {
      resolveRef.current = undefined
  }, [result.loading, result.called])

  const queryLazily: LazyQueryExecute<TData, TVariables> = React.useCallback(
    (variables, context) => {
      execute({ variables, context })
      return new Promise<LazyQueryResult<TData>>((resolve) => {
        resolveRef.current = resolve

  return [

Github User Rank List