Vue组合式函数封装Apollo Mutation的作用域问题咨询
问题原因解析:组合式函数内嵌套调用useMutation丢失Apollo上下文
核心原因:Vue Apollo的上下文依赖组件setup阶段的注入时机
Vue Apollo通过Vue的依赖注入系统传递Apollo客户端实例:useMutation内部会调用inject(APOLLO_CLIENT_KEY)来获取全局或组件树中提供的客户端。这个注入行为只有在组件的setup函数执行期间(或直接在组合式函数的顶层执行时,因为组合式函数本身也是在setup阶段被调用)才能生效,此时组件的上下文处于激活状态。
当你把useMutation包裹在组合式函数的内部函数(比如点击触发的回调、延迟执行的函数)中时,这个内部函数的执行时机是脱离组件setup阶段的:
- 组件setup执行完毕后,Vue的依赖注入上下文会退出激活状态
- 此时调用
useMutation,内部的inject无法找到Apollo客户端的注入值,就会抛出"Apollo client with id default not found"的错误
两种可行写法的逻辑验证
写法1:在组合式函数顶层调用useMutation
// 正确:在组合式函数顶层执行useMutation,处于setup上下文内 export function useMyMutation() { const { mutate: executeMutation } = useMutation(MY_MUTATION, { update(cache, { data }) { // 正常访问mutation参数和缓存 } }) // 返回的执行函数通过闭包保留了已初始化的mutation实例 return { executeMutation } }
这种写法中,useMutation在组件setup阶段(组合式函数被调用时)就完成了客户端的注入获取,后续返回的executeMutation通过闭包持有了已初始化的mutation实例,即使在后续事件中调用,也不需要重新获取上下文。
写法2:手动提供Apollo客户端
// 正确:手动传入客户端,跳过依赖注入 import { provideApolloClient, useMutation } from '@vue/apollo-composable' import { apolloClient } from '../apollo/client' export function useMyMutation() { function executeMutation(variables) { // 临时创建包含指定客户端的上下文,让useMutation能获取到实例 return provideApolloClient(apolloClient)(() => useMutation(MY_MUTATION, { variables, update(cache, { data }) { // 正常编写update逻辑 } }).mutate() ) } return { executeMutation } }
provideApolloClient的作用是临时创建一个包含指定客户端的上下文,让内部的useMutation可以在这个临时上下文中获取到客户端,从而绕过了必须在组件setup阶段执行的限制。
总结
useMutation的上下文依赖组件setup阶段的激活状态,嵌套在延迟执行的内部函数中时,会脱离这个上下文- 组合式函数顶层调用
useMutation,是利用了setup阶段的上下文注入和闭包保留引用 - 手动提供客户端则是通过临时上下文,强制为
useMutation指定客户端实例
内容的提问来源于stack exchange,提问作者overbyte
相关产品推荐
相关产品推荐

