Vue3组合式API中useMutation报错:未找到default Apollo Client
问题:Vue3 + vue-apollo调用useMutation报错"Apollo client with id default not found"
基于Vue3组合式API与vue-apollo开发,调用useMutation向GraphQL端点发送变更请求时出现错误:
Uncaught (in promise) Error: Apollo client with id default not found
此前功能正常,切换Git分支执行npm run build后问题出现,但useQuery仍可正常运行。
变更请求代码
try { const { mutate, onDone, onError, error } = useMutation(ADD_CARDOWNER_MUTATION) mutate({ email: register.email, username: register.email, password: '', first_name: register.firstName, last_name: register.lastName, nfc_user_avatar: register.avatar_id, nfc_user_addresses: register.addresses, nfc_user_contacts: register.contacts, nfc_user_links: register.links, nfc_user_company: register.companyName, nfc_user_position: register.position, nfc_user_title: register.title, nfc_user_position__public: register.positionPublic, nfc_user_company__public: register.companyPublic, nfc_user_agb__accepted: register.agbAccepted, }) onDone((data) => { //formNav.next() console.log('data', data) }) onError(() => { console.log(error.value) }) } catch (error) { console.error(error) }
变更定义ADD_CARDOWNER_MUTATION
mutation AddCardOwner( $email: String $password: String $username: String $first_name: String $last_name: String $nfc_user_addresses: [NFCUserAddress] $nfc_user_contacts: [NFCUserContact] $nfc_user_links: [NFCUserLink] $nfc_user_agb__accepted: Boolean $nfc_user_position__public: Boolean $nfc_user_company__public: Boolean $nfc_user_company: String $nfc_user_position: String $nfc_user_title: String $nfc_user_avatar: String ) { registerNFCUser( input: { email: $email password: $password username: $username first_name: $first_name last_name: $last_name nfc_user_addresses: $nfc_user_addresses nfc_user_contacts: $nfc_user_contacts nfc_user_links: $nfc_user_links nfc_user_agb__accepted: $nfc_user_agb__accepted nfc_user_company__public: $nfc_user_company__public nfc_user_position__public: $nfc_user_position__public nfc_user_company: $nfc_user_company nfc_user_position: $nfc_user_position nfc_user_title: $nfc_user_title nfc_user_avatar: $nfc_user_avatar } ) { nfc_user_id user_id registered username status error } }
main.js配置
import { provide, createApp, defineAsyncComponent, h } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' import './assets/main.css' import UUID from 'vue3-uuid' import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core' import { DefaultApolloClient } from '@vue/apollo-composable' const httpLink = createHttpLink({ uri: import.meta.env.VITE_PUBLIC_API_URI, credentials: 'include', }) const cache = new InMemoryCache() const apolloClient = new ApolloClient({ link: httpLink, cache: cache, }) const app = createApp({ setup() { provide(DefaultApolloClient, apolloClient) }, render: () => h(App), }) const requireComponent = import.meta.glob('./components/**/**/*.vue') Object.entries(requireComponent).forEach(([path, definition]) => { const componentName = path .split('/') .pop() .replace(/\.\w+$/, '') app.component(componentName, defineAsyncComponent(definition)) }) app.use(router) app.use(createPinia()) app.use(UUID) app.mount('#app')
错误截图:
解决方案
1. 改用ApolloProvider全局注入客户端
当前通过根组件setup提供DefaultApolloClient的方式,可能在异步组件场景下存在注入时机问题。替换为createApolloProvider全局注册:
修改main.js:
import { createApp, defineAsyncComponent } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' import './assets/main.css' import UUID from 'vue3-uuid' import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core' // 新增导入createApolloProvider import { createApolloProvider } from '@vue/apollo-option' const httpLink = createHttpLink({ uri: import.meta.env.VITE_PUBLIC_API_URI, credentials: 'include', }) const cache = new InMemoryCache() const apolloClient = new ApolloClient({ link: httpLink, cache: cache, }) // 创建ApolloProvider并指定默认客户端 const apolloProvider = createApolloProvider({ defaultClient: apolloClient, }) // 简化根组件创建,去掉原有的setup和render const app = createApp(App) // 注册ApolloProvider app.use(apolloProvider) const requireComponent = import.meta.glob('./components/**/**/*.vue') Object.entries(requireComponent).forEach(([path, definition]) => { const componentName = path .split('/') .pop() .replace(/\.\w+$/, '') app.component(componentName, defineAsyncComponent(definition)) }) app.use(router) app.use(createPinia()) app.use(UUID) app.mount('#app')
2. 显式指定useMutation使用的客户端
如果全局注入仍不生效,在组件中显式获取客户端并传给useMutation:
import { useMutation, inject } from '@vue/apollo-composable' import { DefaultApolloClient } from '@vue/apollo-composable' import ADD_CARDOWNER_MUTATION from './your-mutation-path.gql' // ... const apolloClient = inject(DefaultApolloClient) const { mutate, onDone, onError, error } = useMutation(ADD_CARDOWNER_MUTATION, { client: apolloClient })
3. 同步依赖版本
切换分支后执行npm install,确保@vue/apollo-composable、@apollo/client等依赖版本与之前正常运行的分支一致,避免版本差异导致的逻辑兼容问题。
4. 验证生产环境变量
确认VITE_PUBLIC_API_URI在生产构建时正确配置,虽然useQuery正常,但环境变量异常可能导致客户端初始化时的缓存或链接异常,间接影响mutation执行。
内容的提问来源于stack exchange,提问作者emmgee
相关产品推荐
相关产品推荐

