• 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

VPS Starter Arubacloud
+2 głosów
393 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 Szeryf (85,260 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 Szeryf (85,260 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 Szeryf (85,260 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

+1 głos
0 odpowiedzi 108 wizyt
pytanie zadane 5 lipca 2022 w JavaScript przez Oskar Szkurłat Bywalec (2,780 p.)
0 głosów
1 odpowiedź 366 wizyt
pytanie zadane 2 maja 2021 w JavaScript przez Bakkit Dyskutant (7,600 p.)
0 głosów
0 odpowiedzi 315 wizyt
pytanie zadane 1 listopada 2022 w JavaScript przez JaaO Początkujący (490 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...