I will take a look at that.
Any progress on this? Tried the apollo module with the new useQuery and get a Error: Apollo Client with id default not found
By the way, is there a workaround to use @nuxtjs/apollo in a nuxt project which uses composition API with @vue/composition-api?
I found an option how to use @vue/apollo-composable. Need to perform a couple of simple steps:
Install @vue/apollo-composable, create plugin provide-apollo-client.ts (name can be any) with the following content:
// plugins/provide-apollo-client.js
import { provide } from '@vue/composition-api';
import { DefaultApolloClient } from '@vue/apollo-composable';
export default ({ app }) => {
app.setup = () => {
const apolloClient = app.apolloProvider.defaultClient;
provide(DefaultApolloClient, apolloClient);
}
}
Specify it in the config with the main API
// nuxt.config.js
plugins: [
'@/plugins/composition-api',
'@/plugins/provide-apollo-client'
],
The rest of the configuration is no different. However, there are still unsolved problems with SSR errors (example: 404 status code).
@negezor I think assigning app.setup = () => { ... } could be a problem if more than one Nuxt plugin want to customize app.setup ... i.e. this is not composable in itself and raises a TS error Type '() => void' is not assignable to type 'SetupFunction<Data, Data>'.
Maybe injecting apolloClient the usual "nuxt way" could work ... I also asked a related question on Discord.
This points to a missing feature of Nuxt for making plugins work nicely with the Composition API.
Following @negezor's plugin, (@lewebsimple and in a more nuxy way via nuxt-composition-api):
// ~/plugins/apollo/provide.ts
import { provide, reactive } from "nuxt-composition-api";
import { Context, Plugin } from "@nuxt/types";
import { ApolloClients } from "@vue/apollo-composable";
const provideApollo: Plugin = ({ app }: Context) => {
app.setup = () => {
// since plugin is eval'd after module app.apolloProvider will always be defined
const clients = reactive(app.apolloProvider?.clients);
provide(DefaultApolloClient, clients?.defaultClient);
// not functionally important but req'd return type
return { [ApolloClients]: clients };
};
};
export default provideApollo;
One important thing to note is that @vue/apollo-composable expects a config named default, whereas @nuxtjs/apollo's default config is named defaultClient. If you provide ApolloClients vs. DefaultApolloClient, you must use { clientId: "defaultConfig" } as an option when calling apollo-composeable.
<template>
{{ result.company.name }}
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
import "vue-apollo"; // just noticed this is here, don't recall why...
import { useCompanyQuery } from "@/generated/graphql-codegen";
@Component({
setup: () => {
const { result, loading, error } = useCompanyQuery({
where: { isParent: true }
});
return { result, loading, error };
}
})
export default class CompaniesCard extends Vue {}
</script>
NB: Companies and Company are different queries.
~For fluency's sake defaultClient needs to be renamed default for interop. with @vue/apollo-composable.~
Edit: Weirdly enough vue-apollo _does_ use defaultClient, and @vue/apollo-composeable uses a different property name.
Hi,
I'm pretty sure I made a mistake somewhere ... I have this error displayed:
const useFetch = (callback) => {
var _a;
const vm = getCurrentInstance();
if (!vm)
throw new Error('This must be called within a setup function.');
registerCallback(vm, callback);
if (typeof vm.$options.fetchOnServer === 'function') {
vm._fetchOnServer = vm.$options.fetchOnServer.call(vm) !== false;
}
nuxt.config.js
buildModules: [
'@nuxt/typescript-build',
'nuxt-composition-api',
],
modules: [
'@nuxtjs/apollo',
],
plugins: [
'~/plugins/provideApolloClient.ts',
],
apollo: {
...
./plugins/provideApolloClient.ts
import { provide, reactive } from 'nuxt-composition-api';
import { Context, Plugin } from '@nuxt/types';
import { DefaultApolloClient } from '@vue/apollo-composable';
const provideApollo: Plugin = ({ app }: Context) => {
app.setup = () => {
// since plugin is eval'd after module app.apolloProvider will always be defined
const clients = reactive(app.apolloProvider?.clients);
provide(DefaultApolloClient, clients?.defaultClient);
// not functionally important but req'd return type
return { [DefaultApolloClient]: clients };
};
};
export default provideApollo;
index.vue
import 'vue-apollo'; // just noticed this is here, don't recall why...
package.json
"dependencies": {
"@nuxt/types": "^2.13.3",
"@vue/apollo-composable": "^4.0.0-alpha.8",
"graphql-tag": "^2.10.4",
"nuxt-composition-api": "^0.10.6",
},
"devDependencies": {
"@nuxtjs/apollo": "^4.0.1-rc.1",
The complet projext:
https://github.com/shenron/vue-nuxt-tsx
Has someone a clue?
Thank you very much.
Edit: Now I don't have errors, just a the page is in pending. The same query works with @nuxt/apollo without composition.
Edit 2: The last version of nuxt-composition-api works with this is: "nuxt-composition-api": "^0.8.2"
There's an update to nuxt-composition-api that provides an onGlobalSetup hook. So now the plugin can just be
(typescript)
import { Context } from "@nuxt/types";
import { provide, onGlobalSetup, defineNuxtPlugin } from "nuxtjs/composition-api";
import { DefaultApolloClient } from "@vue/apollo-composable";
/**
* This plugin will connect @nuxt/apollojs with @vue/apollo-composable
*/
export default defineNuxtPlugin({ app }: Context): void => {
onGlobalSetup(() => {
provide(DefaultApolloClient, app.apolloProvider?.defaultClient);
});
});
and then of course add the plugin
plugins: ["@/plugins/apollo/plugin.ts"]
_edit: use @nuxtjs/composition-api and defineNuxtPlugin_
Just a note from @NickBolles response (which worked perfect for me), the nuxt composition api library is now @nuxtjs/composition-api' so it should be:
import { provide, onGlobalSetup } from '@nuxtjs/composition-api'
Thanks @toddheslin! I've updated the example above to use the new @nuxtjs/composition-api and the defineNuxtPlugin helper too.
Fixed up example
import { Context } from '@nuxt/types';
import { provide, onGlobalSetup, defineNuxtPlugin } from "@nuxtjs/composition-api";
import { DefaultApolloClient } from "@vue/apollo-composable";
/**
* This plugin will connect @nuxt/apollojs with @vue/apollo-composable
*/
export default defineNuxtPlugin(({ app }: Context): void => {
onGlobalSetup(() => {
provide(DefaultApolloClient, app.apolloProvider?.defaultClient);
});
})
Fixed up example
import { Context } from '@nuxt/types'; import { provide, onGlobalSetup, defineNuxtPlugin } from "@nuxtjs/composition-api"; import { DefaultApolloClient } from "@vue/apollo-composable"; /** * This plugin will connect @nuxt/apollojs with @vue/apollo-composable */ export default defineNuxtPlugin(({ app }: Context): void => { onGlobalSetup(() => { provide(DefaultApolloClient, app.apolloProvider?.defaultClient); }); })
My project has an error, please tell me how to solve this problem
Cannot read property 'DefaultApolloClient' of undefined
nuxt - 2.15.3
@nuxtjs/apollo - 4.0.1-rc.5
@nuxtjs/composition-api - 0.22.1
@vue/apollo-composable - 4.0.0-alpha.12
Console error
ERROR [Vue warn]: Error in data(): "TypeError: Cannot read property 'DefaultApolloClient' of undefined"
@Rasool-deldar try @nuxtjs/composition-api - @0.21.0
@Rasool-deldar try @nuxtjs/composition-api - @0.21.0
install @nuxtjs/composition-api - 0.21.0 & 0.20.0
It still shows this error - Cannot read property 'DefaultApolloClient' of undefined
link test ( display error ) - https://codesandbox.io/s/elastic-satoshi-otjer
@Rasool-deldar That link wasn't working but here is what I'm currently using:
"@nuxtjs/apollo": "^4.0.1-rc.5",
"@nuxtjs/composition-api": "^0.21.0",
"@vue/apollo-composable": "^4.0.0-alpha.12"
Now I remember what I had to change to get it to this point...
1) transpile in nuxt.config.js
/*
** Build configuration
*/
build: {
transpile: ['@vue/apollo-composable'],
},
Then, replace all references to import like this (from /dist):
import { DefaultApolloClient } from '@vue/apollo-composable/dist'
That's what I needed to do to move from an earlier version (I've been using it for about a year) till the latest ones)
Hope this helps!
dist
import { DefaultApolloClient } from '@vue/apollo-composable/dist'
Thank you for your help.
I have used this method
import { DefaultApolloClient } from '@vue/apollo-composable'
I have replaced it with the following method
import { DefaultApolloClient } from '@vue/apollo-composable/dist'
I tested it on this version, it worked 0.21.0 & 0.22.3
@nuxtjs/apollo": "^4.0.1-rc.5",
"@nuxtjs/composition-api": "^0.21.0",
"@vue/apollo-composable": "^4.0.0-alpha.12"
@Rasool-deldar That link wasn't working but here is what I'm currently using:
"@nuxtjs/apollo": "^4.0.1-rc.5", "@nuxtjs/composition-api": "^0.21.0", "@vue/apollo-composable": "^4.0.0-alpha.12"Now I remember what I had to change to get it to this point...
- transpile in
nuxt.config.js/* ** Build configuration */ build: { transpile: ['@vue/apollo-composable'], },Then, replace all references to import like this (from /dist):
import { DefaultApolloClient } from '@vue/apollo-composable/dist'That's what I needed to do to move from an earlier version (I've been using it for about a year) till the latest ones)
Hope this helps!
how use ssr ? .
not work ssr
useQuery(
Test,
{},
{
prefetch: true,
}
);
https://codesandbox.io/s/falling-glitter-t4ko2?file=/pages/index.vue:848-938
SSR should just work out of the box. When the page is loaded from the server, the GQL request is made server-side, otherwise it's client.
Not sure what issue you're facing here but glad to know the config changes got the upgrade to work 馃憤
SSR should just work out of the box. When the page is loaded from the server, the GQL request is made server-side, otherwise it's client.
Not sure what issue you're facing here but glad to know the config changes got the upgrade to work 馃憤
I do not know exactly how to handle ssr. Without waiting for the data to go to the server, it goes to the data client, and there it says, please help me, how can I solve this problem? ( localhost - npm run dev )
Look at this link below in the terminal and console, you will see the undefined value on the server side, then the data value will return to the user side.
nuxt-mode ssr: true,
https://codesandbox.io/s/falling-glitter-t4ko2?file=/pages/index.vue:848-938
OK I see your problem here. You can't use async functions in a vue 2.x setup function (ie current version of nuxt). I'll add some commentary:
const movies = ref([]);
// No point doing async/await here because the callback function is called after data is resolved
onResult(async ({ data }) => {
movies.value = await data.movies;
});
// this will always be undefined because we aren't blocking the component from rendering above (and can't)
console.log(result.value);
// same as above
console.log(movies.value);
// setup() is called on both server and client, so it's a bit misleading to log 'ssr' here
console.log("ssr");
The correct way to do it is this:
<script>
import { defineComponent } from "@nuxtjs/composition-api";
import { useQuery, useResult } from "@vue/apollo-composable/dist";
export default defineComponent({
components: {
Logo,
IconLink,
},
setup() {
// not work ssr
const { result, loading, error } = useQuery(
Test,
{},
{
fetchPolicy: "no-cache",
prefetch: true,
}
);
const movies = useResult(result)
return {
movies,
error,
loading,
};
},
});
</script>
In your <template> you can render out movies if we aren't loading or if there is no error. The only time you need to really use onResult() (which I do use a lot) is where you are setting module-scoped refs from a composable that need to be shared state between different components. This is more of an advanced case when you're feeling comfortable with the above.
Check out useResult here: https://v4.apollo.vuejs.org/guide-composable/query.html#useresult
SSR should just work out of the box. When the page is loaded from the server, the GQL request is made server-side, otherwise it's client.
Not sure what issue you're facing here but glad to know the config changes got the upgrade to work 馃憤I do not know exactly how to handle ssr. Without waiting for the data to go to the server, it goes to the data client, and there it says, please help me, how can I solve this problem? ( localhost - npm run dev )
Look at this link below in the terminal and console, you will see the undefined value on the server side, then the data value will return to the user side.
nuxt-mode ssr: true,
https://codesandbox.io/s/falling-glitter-t4ko2?file=/pages/index.vue:848-938
Thank you very much for your help
OK I see your problem here. You can't use async functions in a vue 2.x setup function (ie current version of nuxt). I'll add some commentary:
const movies = ref([]); // No point doing async/await here because the callback function is called after data is resolved onResult(async ({ data }) => { movies.value = await data.movies; }); // this will always be undefined because we aren't blocking the component from rendering above (and can't) console.log(result.value); // same as above console.log(movies.value); // setup() is called on both server and client, so it's a bit misleading to log 'ssr' here console.log("ssr");The correct way to do it is this:
<script> import { defineComponent } from "@nuxtjs/composition-api"; import { useQuery, useResult } from "@vue/apollo-composable/dist"; export default defineComponent({ components: { Logo, IconLink, }, setup() { // not work ssr const { result, loading, error } = useQuery( Test, {}, { fetchPolicy: "no-cache", prefetch: true, } ); const movies = useResult(result) return { movies, error, loading, }; }, }); </script>In your
<template>you can render outmoviesif we aren'tloadingor if there is noerror. The only time you need to really useonResult()(which I do use a lot) is where you are setting module-scoped refs from a composable that need to be shared state between different components. This is more of an advanced case when you're feeling comfortable with the above.Check out
useResulthere: https://v4.apollo.vuejs.org/guide-composable/query.html#useresult
Thank you very much for your help. 馃憤 馃憤 馃憤
Anybody experienced the error of TypeError: defaultClientConfig is undefined here is my plugin:
import {Context} from '@nuxt/types'
import {
provide,
onGlobalSetup,
defineNuxtPlugin
} from '@nuxtjs/composition-api'
import {DefaultApolloClient} from '@vue/apollo-composable/dist'
/**
* This plugin will connect @nuxt/apollojs with @vue/apollo-composable
*/
export default defineNuxtPlugin(({app}: Context): void => {
onGlobalSetup(() => {
provide(DefaultApolloClient, app.apolloProvider?.defaultClient)
})
})
I also added the transpile configuration on my nuxt.config.js
build: {
...
transpile: ['@vue/apollo-composable']
},
Most helpful comment
@Rasool-deldar That link wasn't working but here is what I'm currently using:
Now I remember what I had to change to get it to this point...
1) transpile in
nuxt.config.jsThen, replace all references to import like this (from /dist):
import { DefaultApolloClient } from '@vue/apollo-composable/dist'That's what I needed to do to move from an earlier version (I've been using it for about a year) till the latest ones)
Hope this helps!