Reactjs 使用axios内置自定义反应挂钩

Reactjs 使用axios内置自定义反应挂钩,reactjs,cookies,axios,Reactjs,Cookies,Axios,我想用一个拦截器创建一个全局axios实例,拦截器添加一个带有访问令牌的头。 访问令牌存储在cookie中,但我不知道如何访问拦截器中的cookie,因为它不是react组件 我曾尝试在自定义挂钩中创建axios实例,如下所示: import React, { useEffect, useState } from "react"; import { useCookies } from "react-cookie"; import axios from "axios"; function use

我想用一个拦截器创建一个全局axios实例,拦截器添加一个带有访问令牌的头。 访问令牌存储在cookie中,但我不知道如何访问拦截器中的cookie,因为它不是react组件

我曾尝试在自定义挂钩中创建axios实例,如下所示:

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不是函数


有人能帮忙吗?

问题是您正在尝试使用
react cookie
,它提供了一个用于在组件中使用cookie的api。在某些情况下,这可能没什么问题,但在每次请求都需要检查cookie的情况下,它会强制将
axios
实例放在组件层次结构的顶部,也会使在组件之外使用该实例变得更难(很可能您会将该实例传递给外部函数)

我的建议是在一个单独的模块中创建一个实例,并使用不同的工具来获取cookie

之后,您可以在应用程序中的任何位置使用此实例

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

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

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

这可能是因为
useApiClient.js
中的
useffect
是异步方法

就个人而言,我认为直接将头分配给
axios
对象没有什么害处。但是,我看到您使用的是
axios.create
,因此我假设您可能正在调用多个服务API/端点,而所有这些都不需要相同的头。无论如何

建议

  • 使
    useApiClient
    成为一个简单的类,该类返回带有所需标题的
    axios
    实例。如果没有,我就严重地忽略了在这里使用
    useffect
    的意义
  • 行为

    在每个文件中,您可以调用该文件,并且所有文件都将具有单独的
    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;
    
  • 创建一个Factory类,根据输入参数返回
    axios
    实例(根据传递的参数分配不同的头并返回实例)。如果可行,您也可以将其设置为
    Singleton

  • 希望能有所帮助。

    我注意到的一个问题是,您需要在数组中这样定义客户端依赖关系:
    [client]
    ,在useffect中。你还可以展示一下你是如何使用client.post的吗?嗨@SuleymanSah,谢谢你的评论。我曾尝试在数组中添加依赖项,但没有成功。我已经编辑了我的问题以显示我如何使用客户端。您是否考虑过axios配置的
    withCredentials:true
    选项?
    // apiClient.js
    export function useApiClient() { return apiClient; } 
    
        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;