Cannot call store inside an API with Pinia
Asked Answered
M

1

3

I'm using Vue 3.2 <script setup>, If I try to acess Pinia's store inside an API Service It throws the following error;

Uncaught ReferenceError: Cannot access 'store' before initialization at api.js?:9:1 (anonymous) @ api.js?9:9

src/services/api.js:

import axios from 'axios';
import store from '../stores/index';

// eslint-disable-next-line no-undef

const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL });

if (store) {
  const { token } = store;

  if (token) {
    api.defaults.headers.Authorization = `Bearer ${token}`;
  }
}
console.log(api);

export default api;

src/stores/index.ts:

import { defineStore } from 'pinia'
import Project from '../models/Project';
import { grantAuthSshd, revokeAuth, parseJwt } from '../services/auth';

const initialUser = JSON.parse(sessionStorage.getItem('Orcamento:token') || '{}');

const useProject = defineStore('project-store', {

  state: () => ({
    loading: false as boolean,
  }),

  actions: {
    loadingDataTable(status: ((status: boolean) => void) & boolean) {
      this.loadingDataTable = status;
    },
  }
});

I tried to use Pinia's interceptors but the error persists:

import axios from 'axios';
import useProject from '../stores/index';

const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL });

// use interceptors
api.interceptors.request.use(
  (config) => {
    const { token } = store;
    if ({token}) {
      api.config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
  );
  
const store = useProject();

export default api;
Megara answered 20/9, 2022 at 18:49 Comment(0)
I
3

The problem is that there is indirect circular dependency between services/api.js and stores/index.ts modules, to the point they cannot be evaluated correctly.

useProject() returns a singleton, one of reasons why a store is wrapped with a function is that this prevents it from being accessed too soon. Pinia stores are supposed to be accessed only after Pinia is initialized, otherwise this would require to evaluate the modules that depend on it in a specific order that isn't easy to achieve.

In this case useProject is supposed to be used in-place, not on module evaluation:

api.interceptors.request.use(
  (config) => {
    const store = useProject();
    const { token } = store;
    ...

Due to how ES modules work, this allows to resolve circular dependency.

A way to avoid circular dependency is to move this code from services/api.js to another module that stores/index.ts doesn't depend on, e.g. entry point.

Ingridingrim answered 20/9, 2022 at 21:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.