You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pinia action中正确使用GraphQL mutations实现登录

问题根源

你写的代码有4个核心错误,导致无法正常运行:

  • useMutation是Vue Apollo提供的组合式API,必须在Vue组件setup顶层、或者Pinia Store的初始化顶层调用,你把它写在login普通action内部,每次触发登录才执行调用,拿不到正确的Apollo客户端实例,本身就不符合组合式API的调用规则。
  • 你在action里只解构了mutate方法和onDone回调,根本没有实际调用userLogin()触发登录请求,整个接口请求逻辑根本不会执行。
  • Apollo的mutate操作是异步的,你在组件里调用完authStore.login()就立刻执行路由跳转,此时登录请求还没返回,token还没写入本地和Store,跳转后会因为鉴权失败出问题。
  • 你写的useMutation传参存在语法错误,variables配置项的括号没有闭合。
可行修复方案

按照你的需求(登录逻辑全放Pinia action,组件内仅保留路由跳转),可以按下面的方式改:

1. 修正Pinia Store代码

把useMutation的初始化挪到Store顶层,将login action改为异步函数,用async/await控制请求流程,等token存储完成后再结束action逻辑:

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useMutation } from '@vue/apollo-composable'
import { LOGIN_MUTATION } from '@/api/graphql/mutations' // 替换为你实际的mutation文件路径

export const useAuthStore = defineStore('auth', () => {
  // 登录表单状态
  const formLogin = ref({
    username: '',
    password: ''
  })
  // token状态,初始化时优先读本地缓存
  const accessToken = ref(localStorage.getItem('accessToken') || '')

  // 注意:useMutation必须在Store初始化顶层调用,不能放在action内部
  const { mutate: loginMutate } = useMutation(LOGIN_MUTATION)

  // 异步登录action
  const login = async () => {
    try {
      // 等待登录请求返回结果
      const res = await loginMutate({
        variables: formLogin.value
      })
      const token = res.data.login.token
      // 写入本地存储
      localStorage.setItem('accessToken', token)
      // 写入全局状态
      accessToken.value = token
      // 登录失败逻辑也可以全放这里,比如弹错误提示、重置表单
    } catch (err) {
      console.error('登录失败:', err)
      throw err // 如果需要组件感知错误可以抛出,不需要的话直接在内部处理即可
    }
  }

  return {
    formLogin,
    accessToken,
    login
  }
})

2. 修正组件调用逻辑

组件内调用login action时加await,等所有登录逻辑执行完成、token存储完毕后再执行路由跳转:

<script setup>
import { useAuthStore } from '@/stores/auth'
import { useRouter } from 'vue-router'

const authStore = useAuthStore()
const router = useRouter()

const loginUser = async () => {
  await authStore.login()
  // 组件内仅保留路由跳转逻辑,完全符合你的需求
  router.push({ name: 'Home' })
}
</script>
额外注意事项
  • 所有useXxx开头的组合式API,都必须在setup/Store初始化的顶层同步调用,不能放在普通函数、条件判断、循环中延迟执行,否则会丢失上下文导致报错。
  • 相比onDone回调的写法,直接await mutate返回值的异步控制方式更直观,不会出现时序错乱问题,逻辑更易维护。
  • 如果需要做登录失败的交互(比如错误提示),直接把逻辑写在Pinia action的catch块里即可,组件不需要关心登录相关的任何业务逻辑。

内容的提问来源于stack exchange,提问作者netnull

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:54:31