Ricerca nel sito web

javascript - usare pinia al di fuori di un componente genera errore nessun pinia attivo


Sto lavorando a un progetto Vue.js 3 costruito usando il template ViteSse, voglio usare uno dei miei store Pinia chiamato notificationStore al di fuori del componente setup, ma ottengo l'errore getActivePinia called with no active Pinia. Did you forget to install Pinia quando eseguo il comando dev. Il suo comportamento è così strano perché non si verifica se aggiungo useNotificationStore dopo che il server di sviluppo è stato caricato, e funziona bene, ma quando useNotificationStore esiste nel mio file ts e eseguo il comando dev, genera l'errore.

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 })
  }
)

Ho rintracciato il problema con qualche log e ho scoperto che si è verificato prima che createApp fosse eseguito, che ha avviato Pinia, e in quel momento non c'era alcun Pinia attivo. Mi aspettavo che createApp in main.ts fosse stato eseguito prima di tutto.

grazie in anticipo

Risposta n. 1

Sono riuscito a risolvere il problema leggendo attentamente la documentazione:

Il modo più semplice per garantire che questo sia sempre applicato è rimandare le chiamate di useStore() inserendole all'interno di funzioni che verranno sempre eseguite dopo che Pinia è stato installato.

Ho appena aggiornato http-client rimuovendo useNotificationStore() dalla parte superiore del file e dove ho bisogno dell'istanza notificationStore utilizzo 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 })
  }
)

Risposta n. 2

questo accade perché non hai registrato pinia con l'app

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
    })
  },
)

Si prega di rimuovere useOidcStore() a livello superiore