javascript - שימוש ב-pinia מחוץ לרכיב גורם לשגיאת no active pinia
אני עובד על פרויקט Vue.js 3 שנבנה באמצעות תבנית ViteSse, אני רוצה להשתמש באחד מחנויות Pinia שלי בשם notificationStore מחוץ לרכיב setup אבל אני מקבל את השגיאה getActivePinia called with no active Pinia. Did you forget to install Pinia כאשר אני מריץ את פקודת dev. ההתנהגות שלו כל כך מוזרה כי זה לא קורה אם אני מוסיף את useNotificationStore אחרי שהשרת dev נטען וזה עובד היטב, אבל כאשר useNotificationStore קיים בקובץ ts שלי ואני מריץ את פקודת dev זה מעלה שגיאה.
http-client.ts:
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import axios from 'axios'
import tokenService from './token.service'
import { useNotificationsStore } from '~/store/notification.store'
const notification = useNotificationsStore()
const httpClient: AxiosInstance
= axios.create({
baseURL: `${import.meta.env.VITE_APP_API_URL}/`,
headers: {
'Content-Type': 'application/json',
},
})
httpClient.interceptors.response.use(
(response) => {
if (response.config.method !== 'get') {
const successMsg = 'operation successfully completed'
notification.addNotification({ type: 'success', message: successMsg })
}
return response
},
(error) => {
if (error.message === 'Network Error') {
notification.addNotification({ type: 'error', message: 'Network Error' })
return Promise.reject(error)
}
let errorMessage = ''
const validationErrors = getValidationErrors(error)
errorMessage = getErrorMessage(error)
notification.addNotification({ type: 'error', message: errorMessage, validationErrors, hideAfterRouting: false })
}
)
עקבתי אחרי הבעיה עם קצת לוגים וראיתי שהיא קרתה לפני ש-createApp בוצעה שהתחילה את Pinia ואז לא היה Pinia פעיל באותו זמן. צפיתי ש-createApp ב-main.ts יבוא לפועל לפני הכל
תודה מראש
תשובה #1
הצלחתי לפתור את הבעיה על ידי קריאת התיעוד בקפידה:
הדרך הקלה ביותר להבטיח שזה תמיד ייושם היא לדחות קריאות ל-useStore() על ידי הצבתן בתוך פונקציות שתמיד ירוצו אחרי ש-Pinia מותקן.
הרגע עדכנתי את http-client על ידי הסרת useNotificationStore() מהחלק העליון של הקובץ ובמקום שבו אני צריך מופע של notificationStore אני משתמש ב-useNotificationStore().addNotification(...)
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import axios from 'axios'
import tokenService from './token.service'
const httpClient: AxiosInstance
= axios.create({
baseURL: `${import.meta.env.VITE_APP_API_URL}/`,
headers: {
'Content-Type': 'application/json',
},
})
httpClient.interceptors.request.use(
(config: AxiosRequestConfig) => {
const token = tokenService.getLocalAccessToken()
if (token && config.headers)
config.headers.Authorization = `Bearer ${token}`
return config
},
(error) => {
return Promise.reject(error)
},
)
httpClient.interceptors.response.use(
(response) => {
if (response.config.method !== 'get') {
const successMsg = 'operation successfully completed'
useNotificationsStore().addNotification({ type: 'success', message: successMsg })
}
return response
},
(error) => {
if (error.message === 'Network Error') {
useNotificationsStore().addNotification({ type: 'error', message: 'Network Error' })
return Promise.reject(error)
}
let errorMessage = ''
const validationErrors = getValidationErrors(error)
errorMessage = getErrorMessage(error)
useNotificationsStore().addNotification({ type: 'error', message: errorMessage, validationErrors, hideAfterRouting: false })
}
)
תשובה #2
זה קורה כי לא רשמת את pinia עם האפליקציה
export const createApp = ViteSSG(
App,
{ routes, base: import.meta.env.BASE_URL },
async (ctx) => {
Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true }))
.forEach(i => {
i.install?.(ctx)
})
// install pinia
const pinia = createPinia()
ctx.app.use(pinia)
if (import.meta.env.SSR)
ctx.initialState.pinia = pinia.state.value
else
pinia.state.value = ctx.initialState.pinia || {}
// ============
const DEFAULT_TITLE = 'Dashboard'
ctx.router.beforeEach((to) => {
// ====== use store ====
const { state } = useOidcStore()
if (!store.ready)
// perform the (user-implemented) store action to fill the store's state
store.initialize()
// ===========
if (!state.value.user) {
autoAuthenticate()
}
let title = DEFAULT_TITLE
if (to.meta.title)
title = `${to.meta.title} - ${title}`
document.title = title
})
},
)
אנא הסר את useOidcStore() ברמה העליונה
