جافاسكريبت - استخدام بينيا خارج المكون يرفع خطأ عدم وجود بينيا نشطة
أنا أعمل على مشروع Vue.js 3 تم إنشاؤه باستخدام قالب ViteSse، وأريد استخدام أحد متاجر Pinia الخاصة بي المسمى notificationStore خارج مكون setup، لكنني أتلقى خطأ getActivePinia called with no active Pinia. Did you forget to install Pinia عند تشغيل أمر dev. سلوكه غريب جدًا لأنه لا يحدث إذا أضفت useNotificationStore بعد تحميل خادم التطوير، ويعمل بشكل جيد، ولكن عندما يكون 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() على المستوى الأعلى
