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

Pinia Store调用带i18n的toast函数报setup相关错误如何解决?

报错原因

useI18n 和 vue-toastification 提供的 useToast 都属于Vue组合式API专属钩子,只能在组件setup函数顶层或者在setup顶层调用的组合式函数同步上下文中运行。你在Pinia的action内调用useToastMsg时,执行上下文已经脱离了setup环境,因此触发报错。


可行解决方案

方案1:抽离全局实例,改写composable(最通用,无需依赖调用上下文)

不需要依赖setup环境,改完后组件、Pinia、普通工具函数里都能直接调用。

  1. 单独抽离i18n实例,新建src/i18n/index.js:
import { createI18n } from 'vue-i18n'
// 引入你自己的语言包
import zhCN from './locales/zh-CN.json'
import enUS from './locales/en-US.json'

const i18n = createI18n({
  legacy: false, // 组合式API模式必须设为false
  locale: 'zh-CN',
  messages: {
    'zh-CN': zhCN,
    'en-US': enUS
  }
})

// 导出全局翻译函数,不用再调用useI18n拿t
export const t = i18n.global.t
export default i18n
  1. 在main.js正常注册i18n,同时导出toast全局实例:
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
import Toast from "vue-toastification"
import "vue-toastification/dist/index.css"

const app = createApp(App)
// 注册toast,按你自己的需求填配置
app.use(Toast, {
  position: "top-right",
  timeout: 3000
})
// 导出全局toast实例
export const toast = app.config.globalProperties.$toast

app.use(i18n)
app.mount('#app')
  1. 改写你的toast composable,直接用全局实例,不用调用use钩子:
import { toast } from '@/main'
import { t } from '@/i18n'

export default function useToastMsg(message, type) {
  if (type === "success") {
    return toast.success(t(message))
  } else if (type === "error") {
    return toast.error(t(message))
  }
}

改完后直接在Pinia的action里按原来的写法调用即可,不会再报错。


方案2:调用时传入上下文实例

不想修改现有封装逻辑的话可以用这个方案,在组件调用action时把当前setup上下文的t和toast实例传进去。

  1. 改写composable接收实例参数:
export default function useToastMsg(t, toast, message, type) {
  if (type === "success") {
    return toast.success(t(message))
  } else if (type === "error") {
    return toast.error(t(message))
  }
}
  1. 组件内调用action时传参:
<script setup>
import { useI18n } from 'vue-i18n'
import { useToast } from "vue-toastification"
import { useYourStore } from '@/stores/yourStore'

const { t } = useI18n()
const toast = useToast()
const store = useYourStore()

const handleSubmit = async () => {
  // 调用action时传入t和toast实例
  await store.submitAction(t, toast)
}
</script>
  1. Pinia的action接收参数后调用:
import useToast from "@/composables/toast"

// 选项式写法的store
actions: {
  async submitAction(t, toast) {
    // 你的业务逻辑
    useToast(t, toast, "submit", "success")
  }
}

方案3:Pinia用组合式写法,顶层调用use钩子

如果你用组合式写法定义Pinia store,可以直接在store顶层调用use钩子,符合调用规则:

import { defineStore } from 'pinia'
import { useI18n } from 'vue-i18n'
import { useToast } from "vue-toastification"

export const useYourStore = defineStore('yourStore', () => {
  // store顶层调用use钩子,和组件setup规则一致
  const { t } = useI18n()
  const toast = useToast()

  const submitAction = async () => {
    // 业务逻辑执行完成直接调用
    toast.success(t("submit"))
  }

  return { submitAction }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:54:01