Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onResult does not fire on the first load of useLazyQuery #1543

Open
minako-ph opened this issue Mar 22, 2024 · 7 comments
Open

onResult does not fire on the first load of useLazyQuery #1543

minako-ph opened this issue Mar 22, 2024 · 7 comments

Comments

@minako-ph
Copy link

Describe the bug

When using useLazyQuery, the onResult callback does not fire on the first execution of the load function, even though the result is updated correctly.

To Reproduce

Steps to reproduce the behavior:

  1. Define a useLazyQuery as follows:
const {
  result: myResult,
  load: myLoad,
  onResult: onMyResult,
} = useLazyQuery<MyQuery>(
  MyQueryDocument,
  myQueryVariables,
  {
    clientId: 'myClient',
    fetchPolicy: 'no-cache',
  }
)
  1. Set up an onResult callback:
onMyResult(() => {
  console.log(`📣: onMyResult triggered`)
  isFetched.value = true
})
  1. Trigger the load function based on a condition:
watch(
  myCondition,
  newCondition => {
    console.log(`📣: myCondition changed`, `newCondition: ${newCondition}`)
    if (newCondition) {
      myLoad()
    }
  },
  { immediate: true }
)
  1. Observe the logs:
📣: myResult undefined
📣: myCondition changed newCondition: true
📣: myResult {data: {…}}data: {items: Array(10), totalCount: 10, __typename: 'MyDataType'}[[Prototype]]: Object
📣: myCondition changed newCondition: false
📣: myCondition changed newCondition: true
📣: myResult {data: {…}}
📣: onMyResult triggered

Expected behavior

The onResult callback should be triggered whenever the result is updated, including on the first execution of the load function.

Versions

  • "vue-server-renderer": "2.7.14"
  • "@vue/compat": "3.3.4",
  • "@vue/apollo-composable": "^4.0.2"
  • "@apollo/client": "^3.7.15"

Additional context

The issue seems to be caused by a mismatch in the handling of asynchronous operations between useLazyQuery and useQuery.

In useLazyQuery, the first load returns a Promise that resolves when the query result is received. However, the resolution of this Promise does not directly trigger the onResult callback defined in useQuery.

In useQuery, the onResult callback is triggered by a watch on the result ref. However, this watch does not react immediately to the changes made to result inside the Promise returned by useLazyQuery's load function.

As a result, although myResult is updated after the first load, onMyResult is not triggered until the next load call.

To resolve this issue, we might need to find a way to synchronize the state between useLazyQuery and useQuery, possibly by explicitly triggering the watch in useQuery after result is updated in useLazyQuery, or by making the watch in useQuery aware of the Promise returned by useLazyQuery.

@nickmessing
Copy link
Member

Hello @minako-ph, I could not reproduce this issue.

Can you please create a minimal repro either in a github repo or using codesandbox so the team can debug this issue?

@minako-ph
Copy link
Author

@nickmessing
Thank you for looking into this. I'll prepare a minimal project and share it with you.

As an additional note, I found that downgrading to 4.0.0-beta.9 makes onResult work as expected on the first load, while upgrading to 4.0.0-beta.10 causes onResult to not fire only on the first load. I suspect the following change might be the cause:

useLazyQuery: Load returns Promise, fix #1486 (#1486)

Please let me know if you need any further information. Thank you for your cooperation in resolving this issue.

@nickmessing
Copy link
Member

@minako-ph There's version 4.0.2, did you test on that?

@minako-ph
Copy link
Author

minako-ph commented Mar 27, 2024

@nickmessing

I upgraded from 4.0.0-beta.1 to 4.0.2 and noticed that the onResult stopped firing on the first load completion when using useLazyQuery. As a workaround, I tried downgrading the version. I found that it works up to 4.0.0-beta.9, but stops working from 4.0.0-beta.10 onwards.

Here are the results of my testing:

  • Working
    4.0.0-beta.1
    4.0.0-beta.9

  • Not Working
    4.0.0-beta.10
    4.0.2

@nickmessing
Copy link
Member

@minako-ph

Thank you for investing the time into this. Unfortunately as you can see I couldn't reproduce it in codesandbox (and locally).
If you could please create a minimal repro either as a github project or in codesandbox - that will help us investigate the issue further.

Sorry for the inconvenience

@toknT
Copy link

toknT commented Aug 20, 2024

I am using nuxt/apollo that package using this package , and meet same problem . May onResult fired twice in first load cause it.

nuxt-modules/apollo#633

@janthurau
Copy link

same issue here. I helped myself by also watching result (in addition to providing a callback to onResult).

export default function waitForApolloQuery<TResult, TVariables extends OperationVariables>({
  onResult,
  onError,
  result: apolloResult,
}: Pick<UseQueryReturn<TResult, TVariables>, 'onResult' | 'onError' | 'result'>) {
  return new Promise<TResult | ApolloError | undefined>((res) => {
    const { off: offResult } = onResult((result) => {
      res(result.data);
      setTimeout(offResult, 1);
    });

    watch(apolloResult, () => {
      res(apolloResult.value);
      setTimeout(offResult, 1);
    });

    const { off: offError } = onError((error) => {
      res(error);
      setTimeout(offError, 1);
    });
  });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants