vuejs / apollo

🚀 Apollo/GraphQL integration for VueJS
http://apollo.vuejs.org
MIT License
6.02k stars 521 forks source link

client.watchQuery is not a function #1158

Open mattmeye opened 3 years ago

mattmeye commented 3 years ago

Hello,

I'm learning Vue and just want to create a simple demo of a query with Vue 3 Typescript. What am i doing wrong?

Error: Query is not executed: "TypeError: client.watchQuery is not a function"

HelloWorld.vue

<template>
  <div class="hello">Rooms: {{ result }}</div>
</template>

<script lang="ts">
import { Vue } from "vue-class-component";
import { useQuery } from "@vue/apollo-composable";
import { ref, Ref } from "vue";
import gql from "graphql-tag";

export default class HelloWorld extends Vue {
  result: Ref<any[]> = ref([]);

  created() {
    const { result } = useQuery(gql`
      query listRooms {
        listRooms {
          items {
            id
            name
          }
        }
      }
    `);
    this.result = result;
  }
}
</script>

main.ts

import Auth from "@aws-amplify/auth";
import { DefaultApolloClient } from "@vue/apollo-composable";
import { AWSAppSyncClient } from "aws-appsync";
import { createApp, h, provide } from "vue";
import App from "./App.vue";
import router from "./router";

Auth.configure({
    region: "eu-central-1",
    identityPoolId: "...."
})

const awsAppSyncClient = new AWSAppSyncClient({
    url: "https://.....appsync-api.eu-central-1.amazonaws.com/graphql",
    region: "eu-central-1",
    auth: {
        type: "AWS_IAM",
        credentials: () => Auth.currentCredentials()
    },
    disableOffline: true
}, {
    defaultOptions: {
        watchQuery: {
            fetchPolicy: "cache-and-network"
        },
    }
});

createApp({
    setup() {
        provide(DefaultApolloClient, { default: awsAppSyncClient });
    },
    render() {
        return h(App);
    }
})
    .use(router)
    .mount("#app");
thomasaull commented 3 years ago

I'm having the same problem, did you find any solution/workaround?

thomasaull commented 3 years ago

@mattmeye I figured it out, you need to use this in combination with DefaultApolloClient:

provide(DefaultApolloClient, apolloClient)

The syntax you're using is for multiple apollo clients and needs an import of ApolloClients: https://v4.apollo.vuejs.org/guide-composable/setup.html#multiple-clients

KenEucker commented 1 year ago

@mattmeye did you resolve this issue? I am having the same problem and I haven't been able to find a working solution anywhere.

@thomasaull If this line is a solution: provide(DefaultApolloClient, apolloClient) then where does it go?

thomasaull commented 1 year ago

@KenEucker This is the line which needs to go in the setup function, check the example above:

setup() {
  provide(DefaultApolloClient, { default: awsAppSyncClient });
},
KenEucker commented 1 year ago

@thomasaull unfortunately that doesn't resolve the issue for me.

From my repo: https://github.com/KenEucker/GraphQL-demo

main.ts:

import './style.scss'
import { createApp, h, provide } from 'vue'
import App from './App.vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import apolloClient from './store'
import { MotionPlugin } from '@vueuse/motion'

createApp({
    setup() {
        provide(DefaultApolloClient, { default: apolloClient });
    },
    render() {
        return h(App);
    }
})
    .use(MotionPlugin)
    .mount('#app')

component:

<script setup lang="ts">
  import { computed } from 'vue'
  import { useQuery } from '@vue/apollo-composable'
  import { gql } from '@apollo/client/core'

  // Call the gql function with the GraphQL query
  const query = gql`
    query allAuthors {
      allAuthors {
        id
        firstName
        lastName
      }
    }
  `

  const { result, loading, error } = useQuery(query)
  const list = computed(() => result.value?.authors ?? [])
</script>
<template>
  <div v-if="loading">Loading query...</div>
  <div v-else-if="error">Error: {{ error.message }}</div>
  <div v-else>
    <ul>
      <li v-for="author in list">{{ author.firstName }}</li>
    </ul>
  </div>
</template>
thomasaull commented 1 year ago

@KenEucker Have you tried replacing the line

provide(DefaultApolloClient, { default: apolloClient });

with

provide(DefaultApolloClient, apolloClient)

as per my original comment?

KenEucker commented 1 year ago

@thomasaull that doesn't work either.

thomasaull commented 1 year ago

@KenEucker Can't help you any further I'm afraid :-/

KenEucker commented 1 year ago

@thomasaull thanks for trying.

EDIT: I figured out what my issue was.

It's a very simple and embarrassing issue, but this had to do with how I was exporting my apolloClient. I had the following line:

// apollo.ts (store/index.ts)
...
export default { apolloClient }

Changing that line to the following resolves it:

// apollo.ts
...
export default apolloClient

Finally, here is my main.ts:

import './style.scss'
import { createApp } from 'vue'
import App from './App.vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import apolloClient from './store'
import { MotionPlugin } from '@vueuse/motion'

createApp(App)
    .provide(DefaultApolloClient, apolloClient)
    .use(MotionPlugin)
    .mount('#app')