Pinia报错: “getActivePinia was called with no active Pinia. Did you forget to install pinia?“

关于使用Pinia时提示报错: “getActivePinia was called with no active Pinia. Did you forget to install pinia?” 的原因和解决方案


发生问题的原因

以Vue框架为例, 在main.js中全局注册了pinia, 在axios.js拦截器工具类的全局作用域中使用pinia时发生错误, 提示找不到;
是因为我们在 createApp(App).use(pinia).mount('#app')之前调用了useStore(), 调用时机不对导致的报错;
说简单点, 就是使用pinia store时, pinia插件还没被vue框架初始化。

解决的办法有2种

  1. 使用全局单例对象, 手动集成这三者的加载时机。
  2. 在回调函数中使用useStore(), 也就是确保pinia已经初始化成功再使用 (推荐) *

下面我先附上导致错误的代码示例, 不想浪费时间的, 可以直接跳到解决方案看代码

1. vue全局注册 pinia

main.js
import { createPinia } from 'pinia'

const pinia = createPinia()

createApp(App)
    .use(pinia)
    .mount('#app')

2. 定义 pinia store

store.js
import {defineStore} from "pinia";


export const useCounterStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters:
    {
        // TODO
    },
    actions:
    {
        increment()
        {
            this.count++
        },
        decrement()
        {
            this.count--
        },
    },
})

3. 使用 pinia store

axios.js
import axios from 'axios'
import {useCounterStore} from "@/stores/nutui/store.js";

##### 报错: 重点就是这句话,放在全局作用域中了,导致被提前执行了;检查你的代码是否存在类似的情况 #####
const counterStore = useCounterStore()

// 请求拦截器
axios.interceptors.request.use( function (config)
{
    // TODO 请求之前的预处理
    return config;

}, function (error)
{
    // TODO 请求错误时的预处理
    return Promise.reject(error);
});


// 响应拦截器
axios.interceptors.response.use(function (response)
{
	// 响应之前的预处理
    return response.data;

}, function (error)
{
	// 响应错误时的预处理
    return Promise.reject(error);
});


export default axios

解决方案1 (仅参考)

使用单例模式创建pinia对象

1. 定义 PiniaSingleton

pinia.js
import { createPinia } from 'pinia'

// 单例模式获取 pinia对象
export const PiniaSingleton = (function ()
{
    let instance;

    function createInstance()
    {
        return createPinia();
    }

    return {
        getInstance: function ()
        {
            if (!instance)
            {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

2. vue全局注册 pinia

main.js
// 从自定义单例模式中获取pinia对象
import {PiniaSingleton} from "@/utils/pinia.js";

const pinia = PiniaSingleton.getInstance()

createApp(App)
    .use(pinia)
    .mount('#app')

3. 定义 pinia store

store.js
import {defineStore} from "pinia";


export const useCounterStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters:
    {
        // TODO
    },
    actions:
    {
        increment()
        {
            this.count++
        },
        decrement()
        {
            this.count--
        },
    },
})

4. 使用 pinia store

axios.js
// 从自定义单例模式中获取 pinia对象
import {PiniaSingleton} from "@/utils/pinia.js";

const pinia = PiniaSingleton.getInstance()

const counterStore = useCounterStore(pinia)

// 请求拦截器
axios.interceptors.request.use( function (config)
{
    // TODO 请求之前的预处理
    return config;

}, function (error)
{
    // TODO 请求错误时的预处理
    return Promise.reject(error);
});


// 响应拦截器
axios.interceptors.response.use(function (response)
{
	// 响应之前的预处理
    return response.data;

}, function (error)
{
	// 响应错误时的预处理
    return Promise.reject(error);
});


export default axios

5. 这样就可以在axios.js这个外部文件中正常使用pinia store

useStore(xx)时, 参数中指定pinia全局单例对象即可

PS: 因为useStore(xx)是在全局作用域中使用的, 此时vue-pinia插件环境还没加载出来, 所以需要我们手动设置


解决方案2 (推荐)

准确说, 这不叫解决方案。我们在axios的回调函数中使用pinia就不会报错, 因为axios的回调肯定是在项目初始化完毕才会触发的, 这样就不会出现调用时机不对而导致的错误!

1. vue全局注册 pinia

main.js
import { createPinia } from 'pinia'

const pinia = createPinia()

createApp(App)
    .use(pinia)
    .mount('#app')

2. 定义 pinia store

store.js
import {defineStore} from "pinia";


export const useCounterStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters:
    {
    
    },
    actions:
    {
        increment()
        {
            this.count++
        },
        decrement()
        {
            this.count--
        },
    },
})

3. 使用 pinia store

axios.js
import axios from 'axios'
import {useCounterStore} from "@/stores/nutui/store.js";

// 请求拦截器
axios.interceptors.request.use( function (config)
{
    return config;

}, function (error)
{
    return Promise.reject(error);
});


// 响应拦截器
axios.interceptors.response.use(function (response)
{
	##### 在回调函数中,是可以正常使用useStore(),因为这个时候,pinia已经初始化完毕了 #####
	const counterStore = useCounterStore()
    return response.data;

}, function (error)
{
    return Promise.reject(error);
});


export default axios
  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值