Использование топора ios внутри кастомного реагирующего крючка - PullRequest
1 голос
/ 06 апреля 2020

Я хочу создать глобальный экземпляр axe ios с перехватчиком, который добавляет заголовок с токеном доступа. Токен доступа хранится у повара ie, но я не могу понять, как получить доступ к повару ie внутри перехватчика, поскольку он не является компонентом реакции.

Я попытался создать топор ios экземпляр в пользовательском хуке, как это:

import React, { useEffect, useState } from "react";
import { useCookies } from "react-cookie";
import axios from "axios";

function useApiClient() {
  const [cookies, setCookie] = useCookies(["token"]);
  const [client, setClient] = useState(null);

  useEffect(() => {
    setClient(
      axios
        .create({
          baseURL: "http://localhost:8080/api/",
          responseType: "json",
        })
        .interceptors.request.use(
          (config) => {
            console.log("setting up");
            if (cookies["token"] != null) {
              config.headers.authorization = cookies["token"];
            }
          },
          (error) => Promise.reject(error)
        )
    );
  }, [client]);

  return client;
}

export default useApiClient;

Но когда я пытаюсь вызвать это, используя:

const client = useApiClient();

function attemptLogin() {
    const credentials = {
      username: username,
      password: password,
    };

    client
      .post("/authenticate", JSON.stringify(credentials), {
         headers: {
          "Content-Type": "application/json",
         },
       }).then(....)

, я получаю ошибку ниже:

TypeError: client.post не является функцией

Может кто-нибудь помочь?

Ответы [ 2 ]

4 голосов
/ 14 апреля 2020

Проблема в том, что вы пытаетесь использовать react-cookie, который предоставляет API для работы с файлами cookie в компонентах. Это может быть хорошо для некоторых случаев, но для случая, когда вам нужно проверять куки-файлы при каждом запросе, это заставляет помещать экземпляр axios где-то наверху иерархии компонентов, а также затрудняет использование экземпляра вне компонентов (большинство скорее всего, вы передадите экземпляр внешним функциям).

Я предлагаю создать экземпляр в отдельном модуле и использовать другой инструмент для получения файлов cookie, например universal-cook ie.

// apiClient.js
import axios from "axios";
import Cookies from "universal-cookie";

const cookies = new Cookies();

export const apiClient = axios
  .create({
    baseURL: "http://localhost:8080/api/",
    responseType: "json"
  })
  .interceptors.request.use(
    config => {
      console.log("setting up");
      const token = cookies.get("token");
      if (token != null) {
        config.headers.authorization = token;
      }
    },
    error => Promise.reject(error)
  );

После этого вы можете использовать этот экземпляр повсюду в приложении

import React from 'react';
import { apiClient } from "./apiClient";

export default ({ name }) => {
  useEffect(() => {
    apiClient.get(/*...*/).then(/*...*/);
  });

  return <h1>Hello {name}!</h1>;
}

Если вы предпочитаете придерживаться хуков, вы можете легко обернуть клиента в один:

// apiClient.js
export function useApiClient() { return apiClient; } 

Игра с полным примером

0 голосов
/ 19 апреля 2020

Это может быть потому, что useEffect в useApiClient.js является асинхронным c методом.

Лично я не вижу вреда в прямом назначении заголовков для объекта axios. Однако я вижу, что вы используете axios.create, поэтому я предполагаю, что вы, возможно, делаете вызовы к нескольким API / конечным точкам служб, и всем не нужны одинаковые заголовки. В любом случае ...

Предложения

  1. Сделать useApiClient простым классом, который возвращает экземпляр axios с необходимыми заголовками. Если нет, то я серьезно упускаю смысл использования useEffect здесь.

Поведение

В каждом файле, который вы подаете, вызывайте это, и у всех будет отдельный экземпляры axios без загрязнения глобального объекта axios.

useApiClient.js

    function useApiClient {
        return axios
          .create({
            baseURL: "http://localhost:8080/api/",
            responseType: "json"
        })
        .interceptors.request.use(
          config => {
            console.log("setting up");
            const token = cookies.get("token");
            if (token != null) {
              config.headers.authorization = token;
            }
          },
          error => Promise.reject(error)
        );
      }
    }

    export default useApiClient;
Создает фабричный класс, который возвращает axios экземпляров на основе входного параметра (чтобы назначить разные заголовки на основе переданного параметра и вернуть экземпляр). Вы также можете иметь значение Singleton, если это возможно.

Надеюсь, это поможет.

...