Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Cannot query on button click? (in v4 composition API) #909

Closed
ozum opened this issue Jan 17, 2020 · 22 comments
Closed

Cannot query on button click? (in v4 composition API) #909

ozum opened this issue Jan 17, 2020 · 22 comments

Comments

@ozum
Copy link

ozum commented Jan 17, 2020

Thanks for the library and effort given.

Similar to #121, I need an example how to query after an event (such as button click) in v4 composition API?

Further info:
I'm using vue-apollo with Nuxt. (Not @nuxtjs/apollo, because it doesn't support vue-apollo v4 yet.)

I tried below methods:

setup(props, context) {
  const enabled = ref(false)
  const q1 = useQuery(someQuery); // This is OK.

  // When I add below line, browser hangs during page load and waits forever.
  const q2 = useQuery(someQuery, null, { enabled: enabled.value });

  // Click handler throws when executed on click event.
  // Cannot read property '$isServer' of null at useQuery (useQuery.js?a2fd:25)
  function onClick() {
    const q3 = useQuery(someQuery);
  }
}

Many thanks,

@ozum ozum changed the title How to do query on button click? (in v4 composition API) Cannot query on button click? (in v4 composition API) Jan 21, 2020
@maxstue
Copy link

maxstue commented Feb 24, 2020

Hi,

i searched for it a lot too, but it is writtin in their documentation vue apollo v4e

import { useQuery, useResult } from '@vue/apollo-composable'
import gql from 'graphql-tag'

export default {
  setup () {
    const { result, loading, error, refetch } = useQuery(<query>)

    const users = useResult(result)

    return {
      users,
      loading,
      error,
      refetch,
    }
  },
}
</script>

<template>
  <div v-if="loading">Loading...</div>

  <div v-else-if="error">Error: {{ error.message }}</div>

  <ul v-else-if="users">
    <li v-for="user of users" :key="user.id">
      {{ user.firstname }} {{ user.lastname }}
    </li>

    <button @click="refetch()">Refresh</button>
  </ul>
</template>

just add the "refetch" to the useQuery line and call it from the button click event.

Best Regards

@ozum
Copy link
Author

ozum commented Feb 25, 2020

@lTimeless, thanks for the answer. Does the example query the server two times (one in setup and one in refetch) or only one time (in refetch)?

Thanks.

@maxstue
Copy link

maxstue commented Feb 25, 2020

@ozum You could Disable the query and on button click enable it andthan refetch the query.
Or set the polling interval really high and then refetch it on button click.
Maybe there is another way, but i couldn't find anything else so far.

@ozum
Copy link
Author

ozum commented Feb 25, 2020

@lTimeless thanks for the answer.

@aaronschweig
Copy link

Hello @ozum I'm experiencing the same issue.
Did you find any solution that works without sending the query twice? For me the enable-Approach did work, but I think it would be cleaner if you just have to enable the quer without explicitly refetching it. Maybe you have found somethin?

@ozum
Copy link
Author

ozum commented Feb 28, 2020

@aaronschweig currently I have to switch back to old API, because some of the libraries I use did not support composition API yet. Using old API, I could not find a solution other than enable approach.

@mtsmachado8
Copy link

Hello guys, any solution for it yet? same problem.
Cannot read property '$isServer' of null at useQuery

@aaronschweig
Copy link

aaronschweig commented Apr 26, 2020

Hello @mtsmachado8 i've found a working solution.

const queryOptions = ref({
  // whatever options you need
  enabled: false
})

const {result} = useQuery(<query>, <variables>,queryOptions)

// Do with the result what you need

const onClick = () => {
  queryOptions.value.enabled = true
}

This works for me and queries only once, when the Button is clicked. For me, instead of only doing the enabled as a ref, using the whole options-obejct as a ref did the trick.After that, if you want to requery on every click, you can use the refetch-Option from the useQuery like

const {result, refetch} = useQuery(<query>, <variables>,queryOptions)

const onClick = () => {
  if (!queryOptions.value.enabled) {
    queryOptions.value.enabled = true
    return 
  }
  refetch()
}

I hope this helps!

@mtsmachado8
Copy link

Thankss @aaronschweig, it really helped!!!

@datrinh
Copy link

datrinh commented Jun 25, 2020

This seems very inelegant. Executing a query on click (or whatever event) should work as expected imo.

@seanaye
Copy link

seanaye commented Aug 17, 2020

Is there a solution for this if you arent even using an event to trigger query? I'm using quasar ssr and am getting Error in data(): "TypeError: Cannot read property '$isServer' of null" in build ssr but no such error in dev ssr.

There is nothing special triggering the query its just within the setup function.

@leonsilicon
Copy link

Is there a way to prevent the initial query from executing with useQuery? My code is written as follows:

export default function useUserQuery() {
  const { refetch } = useQuery(UserQuery);

  return async function fetchUser(userId) {
    const { data } = await refetch({ userId });
    return data.user;
  };
}

This works as intended, but the initial query is being run (without variables and thus is throwing an error in the console, but all subsequent queries with fetchUser(userId) work perfectly fine). I've tried using the enabled option but it seems like when you set enabled.value = true the query gets automatically re-run (and the value stored in result), which wouldn't work in my situation since I want to capture the result of the query in a callback (in this case, const {data} = await refetch({ userId })).

@rebz
Copy link

rebz commented Oct 20, 2020

Can you get this disable/enable demo to work with the latest alpha version?
#1082

@Akryum
Copy link
Member

Akryum commented Oct 20, 2020

useLazyQuery

@IlCallo
Copy link

IlCallo commented Nov 27, 2020

Both useLazyQuery usage and the fact that refetch returns a Promise to the fetched data are missing from the docs :\

@IlCallo
Copy link

IlCallo commented Nov 27, 2020

Also, seems like there's no clean way to perform a one-shot request or reuse the same one on-demand (without loading it first).

In Options API you could do this

const result = await this.$apollo.query({
  query: gql`...`,
  variables: { param: 'hello' },
})

You still can, via context.root

const result = await root.$apollo.query({
  query: gql`...`,
  variables: { param: 'hello' },
})

Using load from useLazyQuery will "unblock" the query, which will start immediately, but won't return the answer if awaited.
My use case is a "search" which hits the databases as part of a multi-step filtering of the results. The order of the filters is important, so I must call them synchronously and only on-demand.

I guess I could create a Promise which wraps the result ref and resolve when it emits, but it feels a bit hacky.
Will keep using previous syntax in the meantime, keep up the good work!

@paulhaem
Copy link

Besides useLazyQuery still not being documented its unable to parse queries useQuery is not having any problems with throwing a Invariant Violation error.

@joelmandell
Copy link
Contributor

joelmandell commented Jun 14, 2021

@paulhaem Getting that error as well.
image

And example-code that triggers the error above. It is in a vuex-module.
image

In my component it is returned with spread syntax.
image

And in the template:
image

@joelmandell
Copy link
Contributor

joelmandell commented Jun 14, 2021

I tried to do this instead now @Akryum:

image

And I am getting this error in console (catching it in a try/catch):

image

Update: I saw that I missed to pass variable, but I changed that and I'm getting the error anyway.

@joelmandell
Copy link
Contributor

In firefox console getting this error:

image

@joelmandell
Copy link
Contributor

Might be on track to something. This issue pointed me in right direction: #1029 (comment)

I do not use Vite-plugin, so I removed it manually...

@Gin-Quin
Copy link

Gin-Quin commented Oct 14, 2021

The right way to do it is not to use useQuery neither useLazyQuery but instead useApolloClient like this:

import { useApolloClient } from '@vue/apollo-composable'

const { client } = useApolloClient()

const onClick = async () => {
  const { data } = await client.query({
    query: someQuery,
    variables: someVariablesIfNeeded,
  })
}

@vuejs vuejs locked and limited conversation to collaborators Nov 28, 2021
@Akryum Akryum closed this as completed Nov 28, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests