• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

React Axios - gdzie przechowywać defaultową konfigurację oraz własne funkcje konfigurujące

+2 głosów
265 wizyt
pytanie zadane 1 maja 2019 w JavaScript przez kevin Mądrala (5,010 p.)

Cześć,

Mam do Was pytanie ponieważ jestem na początku nauki Reacta i nie chcę sobie na początku czegoś namieszać tylko bardziej potrzebuję subiektywnej oceny tego co robię. Gdzie trzymacie własne funkcję konfigurujące paczki np. axios ? To nie jest helper więc nie ma sensu tam go pchać ale folder /src/config jest podobno zajęty przez inną logikę ? Pytanie nie tylko dotyczy konfiguracji axiosa ale jeżeli ma logikę która wymaga takiej konfiguracji to gdzie ja powinienem trzymać takie funkcje? Tutaj mam przykładowy kod który wykonuje się z każdym requestem do tej pory trzymam go w pliku index.js ale nie chcę trzymać tam wszystkiego jedynie wywołania funkcji.

const axiosInterceptorsRequestConfig = store => {
    axios.interceptors.request.use(request => {
        const token = store.getState().auth.token;
        if (token) {
            request.headers.Authorization = token;
        }

        return request;
    }, error => {
        return Promise.reject(error);
    });
};

const axiosInterceptorsResponseConfig = store => {
    axios.interceptors.response.use(response => {
        return response;
    }, error => {
        if (error.response.status === 401) {
            store.dispatch(authActions.logout());
        }

        return Promise.reject(error);
    });
};

Do ustawień axiosa mogę dodać adres który będzie zawsze doklejany do zapytań, ale co jeżeli będę chciał strzelić gdzieś indziej axiosem ? Chyba nie ma możliwości zmiany domyslych ustawien na jeden request ?

axiosDefaults.baseURL = 'http://somesite.com';

Czytałem o pewnym rozwiązaniu:

// sender.js

import axios from 'axios;

export const axiosInstance = axios.create({
  baseURL: 'http://somesite.com',
  /* ... */
});

Czyli robię sobie Instancje axiosa i ją konfiguruję na potrzeby swojego API, dodaję odpowiednie interceptors'y i normalnie używam tylko czy nie jest to źle że za każdym requestem jeszcze raz robię nową instancję ? Nie zapisuję tego nigdzie stale. A dla adresów nie należących do mojego api tworzę inną instancję. Tylko czy axios.create tworzy nową instancję na podstawie domyślnych ustawień ? Jeżeli mam dodane globalnie jakieś interceptors'y i inne konfigi to po użyci funkcji axios.create automatycznie znajdą się w nowej instancji ?

1 odpowiedź

+1 głos
odpowiedź 2 maja 2019 przez rafal.budzis Maniak (65,960 p.)

Jeśli coś nie jest helperem można z tego zrobić helpera! :D Temu co sam bym zrobił bliski jest ostatni przykład. Zamknąć wszystko dotyczące axiosa w jednym pliku i nazwać go ajax, fetch czy zaproponowany sender. Jednak na początek musisz zrozumieć ze moduły są cachowane. Gdy ich kod się wykona zapamiętywane są tylko wartości zmiennych które exportujesz. Zrób sobie dla testów przykładowy moduł.

export const sum = 2 + 2;

console.log('2+2 = ', sum);

export const getSum = () => sum;

spróbuj teraz zaimportować moduł i postarać się aby console.log wykonał się drugi raz. Podpowiem ze się nie da ;) Moduły JS są wykonywane w całości i JS zapamiętuje tylko wartości które eksportuje moduł.

Wracając do twojego przykładu na Twoim miejscu zrezygnował bym z nazewnictwa axios poza plikiem tak aby łatwo podmienić bibliotekę jeśli zajdzie taka potrzeba ;)

Zrobił bym coś w stylu :

import axios from 'axios;
 
const axiosInstance = axios.create({
  baseURL: 'http://somesite.com',
  /* ... */
});

export const get = (resource, data) => axiosInstance.get(....);

Zaznaczam ze nie znam axiosa więc nie wiem czy posiada on metode get. Ale metodę get eksportował bym z pliku który miałby zarządzać ajaxem. Mi osobiście bardzo się podobają nazwy funkcji wskazujące na metodę http (GET, POST, PUT, PATCH, DELETE).

psssyt kevin czy ty nie siedzisz obok mnie w pracy? Mam takie dziwne przeczucie :D

 

komentarz 2 maja 2019 przez kevin Mądrala (5,010 p.)

Wracając do twojego przykładu na Twoim miejscu zrezygnował bym z nazewnictwa axios poza plikiem tak aby łatwo podmienić bibliotekę jeśli zajdzie taka potrzeba ;)

Tak w końcowym efekcie właśnie to chciałem osiągnąć, opakować wysyłanie w coś typu:

// sender.js

import axios from 'axios;

export const apiCallInstance = axios.create({...});

export const apiCall = (url, method, data, resolve, reject) => {
        axios({
        method: method,
        url: url,
        data: data
    })
        .then(response => resolve(response))
        .catch(error => reject(error))
    ;

};


// apiCategories.js
import {apiCall} from 'sender.js';

export const getCategories = () => new Promise(
    (resolve, reject) => apiCall("/api/categories", 'get',  null, resolve, reject)
);

export const createCategory = (data) => new Promise(
    (resolve, reject) => apiCall("/api/categories", 'post',  data, resolve, reject)
);


Fajnie opisałeś cachowanie tego dzięki! Ale żebym ja przełożył teraz to na to co potrzebuję to jeżeli w module będę tworzył nową instancję to tak naprawdę to się to znajdzie w cachu i nie będzie takie problemu że za każdym razem tworze nową instancję. I rozwiązuje to problem z defaultowym konfigu w axiosie jeżeli nagle będę chciał strzelić requestem do innej domeny. Dobrze zrozumiałem ?

psssyt kevin czy ty nie siedzisz obok mnie w pracy? Mam takie dziwne przeczucie :D

Hmm.... pracuje w Lublinie, a Ty ?

1
komentarz 3 maja 2019 przez rafal.budzis Maniak (65,960 p.)

Dobrze zrozumiałeś ;) Jednak masz troche pogmaatwany kod z przekazywaniem tych resovle i reject jako callbacki. Można to uprościć do takiej formy:

// sender.js
 
import axios from 'axios;
 
export const apiCallInstance = axios.create({...});
 
export const apiCall = (url, method, data) => {
        axios({
        method: method,
        url: url,
        data: data
    })
        .catch(error => Promise.reject(error))
    ;
 
};
 
 
// apiCategories.js
import {apiCall} from 'sender.js';
 
export const getCategories = () => apiCall("/api/categories", 'get',  null);
 
export const createCategory = (data) => apiCall("/api/categories", 'post',  data);

Ja pracuje w Wrocku. Wychodzi na to ze dziwny zbieg okoliczność :D Po prostu imię, temat  i czas pasowały. Kilka dni temu dokładnie tym się zajmował  (axios w React) Kewin z Wrocka :D 

komentarz 3 maja 2019 przez kevin Mądrala (5,010 p.)

Dzięki za pomoc. Więc robię helper tworzący nową instancję ale tutaj się zgubiły te interceptors'y ustawiające token w header oraz sprawdzające status w response. W pliku helpera nie mam dostępu do store ( albo jeszcze nie wiem że mam ) więc dla uproszczenia:

// api_sender.js
  
import axios from 'axios;
  
export const apiCallInstance = () => {
         const instance = axios.create({...});
        
         instance.interceptors.request.use(request => {
        const token = localStorage.getItem('token');
        if (token) {
            request.headers.Authorization = token;
        }

        return request;
    }, error => {
        return Promise.reject(error);
    });

    instance.interceptors.response.use(response => {
        return response;
    }, error => {
        if (error.response.status === 401) {
            
           // ERROR bo nie ma store
           store.dispatch(authActions.logout());
        }

        //  if (error.response.status === 404) {
        //     history.push('/not-found');
        // }
        return Promise.reject(error);
    });

   return instance;
};  

Nie wiem czy kombinuję w dobrą stronę ale nie chcę samemu w każdym wywołaniem funkcji wpisywać token z użyciem interceptors'a się to automatyzuje. Ale jak poprawnie tego użyć ? Identyczna sytuacja z response, potrzebuję store i history. Więc na pewno prościej jest użyć globalnie interceptors'a i tworzyć instancje dla zapytań które idą poza api ale czy poprawnie ?

Ja pracuje w Wrocku. Wychodzi na to ze dziwny zbieg okoliczność :D Po prostu imię, temat  i czas pasowały. Kilka dni temu dokładnie tym się zajmował  (axios w React) Kewin z Wrocka :D 

Dziwny i można powiedzieć że miasta mają podobną odległość do sąsiednich krajów :D

komentarz 4 maja 2019 przez rafal.budzis Maniak (65,960 p.)
Wydaje mi się ze axios.create powinieneś dać gdzieś wyżej. Ale niestety nie za dużo z tym pomogę bo nie znam axiosa.

Podobne pytania

0 głosów
1 odpowiedź 91 wizyt
pytanie zadane 2 maja w JavaScript przez Bakkit Mądrala (6,710 p.)
0 głosów
0 odpowiedzi 57 wizyt
pytanie zadane 7 kwietnia w JavaScript przez Utlamo Użytkownik (980 p.)
Porady nie od parady
Nie wiesz jak poprawnie zredagować pytanie lub pragniesz poznać którąś z funkcji forum? Odwiedź podstronę Pomoc (FAQ) dostępną w menu pod ikoną apteczki.FAQ

85,698 zapytań

134,499 odpowiedzi

298,513 komentarzy

56,625 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...