javascript - bruk av pinia utenfor komponent gir feil om ingen aktiv pinia
Jeg jobber med et Vue.js 3-prosjekt bygget med ViteSse-mal. Jeg vil bruke en av mine Pinia-butikker kalt notificationStore utenfor setup-komponenten, men jeg får getActivePinia called with no active Pinia. Did you forget to install Pinia-feil når jeg kjører dev-kommandoen. Oppførselen er så merkelig fordi det ikke skjer hvis jeg legger til useNotificationStore etter at dev-serveren er lastet, og det fungerer bra, men når useNotificationStore finnes i ts-filen min og jeg kjører dev-kommandoen, oppstår feilen.
http-klient.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 })
}
)
Jeg har sporet problemet med litt logging og funnet ut at det skjedde før createApp ble utført som initierte Pinia, og det var ingen aktiv Pinia på det tidspunktet. Jeg forventet at createApp i main.ts hadde blitt utført før alt.
takk på forhånd
Svar #1
Jeg klarte å løse problemet ved å lese dokumentasjonen nøye:
Den enkleste måten å sikre at dette alltid blir brukt på, er å utsette kallene til useStore() ved å plassere dem inni funksjoner som alltid vil kjøre etter at pinia er installert.
Jeg oppdaterer nettopp http-klienten ved å fjerne useNotificationStore() fra toppen av filen, og der jeg trenger en notificationStore-instans, bruker jeg 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 })
}
)
Svar #2
dette skjer fordi du ikke har registrert pinia med appen
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
})
},
)
Vennligst fjern useOidcStore() på topplivå
