javascript - 在組件外使用 pinia 會引發沒有活動 pinia 的錯誤
我正在使用 ViteSse 模板構建的一個 Vue.js 3 項目中工作,我想在 setup 組件之外使用我其中一個名為 notificationStore 的 Pinia store,但當我運行開發命令時,出現了 getActivePinia called with no active Pinia. Did you forget to install Pinia 錯誤。它的行為非常奇怪,因為如果我在開發服務器加載後再使用 useNotificationStore,則不會出現此錯誤,並且可以正常工作,但當 useNotificationStore 存在於我的 ts 文件中並運行開發命令時,就會引發錯誤。
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 之前,而 createApp 是用來初始化 Pinia 的,那時候還沒有活動的 Pinia。我原本預期 main.ts 中的 createApp 會在所有之前就已經被執行。
提前感謝
答案#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()
