我想用拦截器创建一个全局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不是函数
有人可以帮忙吗?
答案 0 :(得分:4)
问题是您试图使用react-cookie
来提供用于处理组件中cookie的api。在某些情况下可能会很好,但是对于当您需要在每个请求上检查cookie的情况下,它会强制将axios
实例放置在组件层次结构的顶部,并且使在组件之外使用该实例更加困难(最有可能将实例传递给外部函数)。
我建议在一个单独的模块中创建一个实例,并使用其他工具来获取universal-cookie之类的cookie。
// 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; }
答案 1 :(得分:0)
这也许是因为useEffect
中的useApiClient.js
是异步方法。
我个人认为直接将标题分配给axios
对象没有什么害处。但是,我看到您正在使用axios.create
,因此我假设您可能正在调用多个Service API /端点,并且所有这些都不需要相同的标头。反正...
建议
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
。希望有帮助。