Dostęp do router.currentRoute poza komponentem

0

Witajcie,
nie mam sporego doświadczenia w VUEJS jak i w samym JS, stąd prawdopodobnie ugrzązłem na wydawałoby się dość trywialnym temacie.

Słowem wyjaśnienia projekt to aplikacja SPA mająca się komunikować z backendem via REST API a postawiona jest na VITESSE (boilerplate VUE3+Typescript+Pinia+composition API ....)

Postanowiłem jako, że aplikacja z założenia będzie dość złożona wydzelić warstwę komunikującą się po HTTP.

W związku z powyższym stworzyłem folder /src/api a w nim kolejne pliki z podzielonymi na grupy metodami wykonującymi konkretne zapytania via axios (jak niżej)

import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import axios from 'axios'
import { router } from '~/main'


const axiosInstance: AxiosInstance = axios.create({
  baseUrl: import.meta.env.API_URL,
  headers: {
    'Content-type': 'application/json',
    'Authorization': 'Bearer ' + 'TOKENXXXXXXXXXXXXX',
    'Language': router.currentRoute.value.params.lang,
  },
})

async function axiosCall<T>(config: AxiosRequestConfig) {
  try {
    const { data } = await axiosInstance.request<T>(config)
    return [null, data]
  }
  catch (error) {
    return [error]
  }
}

export async function sendMessage(formData) {
  return axiosCall<void>({ method: 'post', url: '/send-message', data: formData })
}

OPIS PROBLEMU

W headerach chciałbym umieszczać aktualnie wybrany język przez usera do backendu:

 'Language': router.currentRoute.value.params.lang,

problem tylko w tym że router jest w tym momencie "niezainicjowany".

Mimo że jestem na ścieżce /en/contact to router.fullPath pokazuje "/", a router.currentRoute.value.params jest pustym obiektem

jednak jak wykonam coś takiego w powyższym pliku:

async function getLang() {
  await router.isReady()
  console.log('routerLang:', router.currentRoute.value.params.lang)
}

getLang()

to oczywiście na konsoli bez zająknięcia pojawia się "routerLang: en"

Oczywiście obejściem jest wyekstrahowanie języka z dostępnego w tym etapie: window.location.href jednak to z pewnością niezgodne ze sztuką

Jak z takimi problemami sobie radzić ?

Pozdrawiam i z góry dziekuję

0

Konfiguracje Axiosa możesz sobie nadpisać (https://axios-http.com/docs/config_defaults)

const axiosInstance: AxiosInstance = axios.create({
  baseUrl: 'https://xxx.pl/api/',
})

axiosInstance.defaults.baseUrl = 'https://zzz.com/api/v2/';

więc ja na Twoim miejscu stworzyłbym sobie funkcję

export const setAxiosLanguage = (language: string): void => {
  axiosIstance.defaults.headers.common['Language'] = language;
}

i używałbym jej w tych komponentach, które odpowiadają za zmianę języka

0
Xarviel napisał(a):

Konfiguracje Axiosa możesz sobie nadpisać (https://axios-http.com/docs/config_defaults)

const axiosInstance: AxiosInstance = axios.create({
  baseUrl: 'https://xxx.pl/api/',
})

axiosInstance.defaults.baseUrl = 'https://zzz.com/api/v2/';

więc ja na Twoim miejscu stworzyłbym sobie funkcję

export const setAxiosLanguage = (language: string): void => {
  axiosIstance.defaults.headers.common['Language'] = language;
}

i używałbym jej w tych komponentach, które odpowiadają za zmianę języka

Witaj,
dziękuję, że zechciałeś się pochylić nad tematem. Tak jak pisałem, nie jestem specjalnie biegły w temacie zakulisowych zdarzeń w VUE/JS i to co wpisałeśz konfiguracją Axiosa rozumiem, ponieważ już korzystałem z takiego podejścia tylko mam wątpliwość gdzie taka funkcja powinna zostać ulokowana ponieważ nie mam dedykowanych komponentów odpowiadających za zmianę języka (co może właśnie być złym podejściem)?

Na ten moment jeśli użytkownik wejdzie na /en/contact to uznaję że ustawił sobie język na angielski tak samo jak na /de/configurator to zaczynam rozmawiać z nim po niemiecku.
i18n robi to po stronie frontu w oparciu o routing w App.vue -> i to również dzieje się PO zaczytaniu się mojego /src/api/contact.ts

Będę wdzięczny za jeszcze jakąś podpowiedz

Pozdrawiam

0

Musisz po prostu w jakimś komponencie wykryć jaki jest obecny język i zmienić konfiguracje axiosa (https://stackoverflow.com/questions/67141277/is-there-a-way-to-watch-a-change-of-the-i18ns-current-locale)

W teorii powinno to być coś takiego...

<script setup lang="ts">
import { useI18n } from 'vue-i18n';
// import { setAxiosLanguage } from '..'; <-- tutaj importujesz tą wcześniejszą funkcję, którą zrobiłem

const { t, locale } = useI18n();

watch(locale, () => {
  console.log('locale', locale.value);

  // setAxiosLanguage(locale.value);
});
</script>

ale jak będzie w praktyce to nie wiem, ciężko to ocenić na podstawie jednego pliku

0

Dziękuję za po raz kolejny poświęcony czas. Zamysł rozumiem, ale...

Od 3h kombinuję i wydaje mi się, że to tak nie zadziała.

W ogólności mówię o tym, że w moim pliku xxx.ts gdzie mam cała logikę API i tworzę instancję klienta axios nie ma jeszcze zainicjowanego routera ...i nie ma go też w żadnym pliku, który ładuje się przed nim. Pełnowartościowe komponenty mające dostęp do routera ładują się zawsze po pliku xxx.ts.

Efekt jest taki że jak dodam wpis:

axiosIstance.defaults.headers.common['Language'] = 'xyz';

w jakimkolwiek pliku, który ładuje się przed xxx.ts (np. main.ts) to zapytanie uwzględni to i request posiada ten nagłówek, natomiast gdy dodam to w jakimkolwiek ładowanym później (np. App.vue), już nie.

Utknąłem :(

Zastanawiam się nad stworzeniem instancji samego klienta REST API jako composables a jedynie same endpointy (funkcje obsługujące konkretne zapytania) jakoś umieścić w /src/api/xxxxx.ts (jeden plik to jeden set dziedzinowo powiązanych metod)

to powinno rozwiązać problem z inicjalizowaniem samej instancji axiosa (a przynajmniej tak mi się wydaje...) jednak nie wiem jak to sprytnie ograć :(

1 użytkowników online, w tym zalogowanych: 0, gości: 1