我无法弄清楚为什么未在此函数中调用useContext:
import { useContext } from "react";
import { MyContext } from "../contexts/MyContext.js";
import axios from "axios";
const baseURL = "...";
const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
.
.
.
});
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const { setUser } = useContext(MyContext);
console.log("anything after this line is not running!!!!");
setUser(null)
.
.
.
我的目标是使用拦截器来检查令牌是否处于活动状态,以及是否无法清除用户并登录。我在其他React组件中使用了相同的上下文。它在那里工作正常,只是不在这里运行!知道我在做什么错吗?
答案 0 :(得分:1)
我和你有同样的问题。这是我的解决方法:
您只能在功能组件中使用useContext
,这就是为什么您不能在axios拦截器中执行setUser
的原因。
您可以做的是创建一个名为WithAxios
的单独文件:
// WithAxios.js
import { useContext, useMemo } from 'react'
import axiosInstance from '../../axios'
import NotificationContext from '../Notification/NotificationContext'
const WithAxios = ({ children }) => {
const { setUser } = useContext(MyContext);
useMemo(() => {
axiosInstance.interceptors.response.use(response => response, async (error) => {
setUser(null)
})
}, [setUser])
return children
}
export default WithAxios
然后在WithAxios
之后添加MyContext.Provider
,以访问您的上下文,例如:
// App.js
const App = () => {
const [user, setUser] = useState(initialState)
return (
<MyContext.Provider value={{ setUser }}>
<WithAxios>
{/* render the rest of your components here */}
</WithAxios>
</MyContext.Provider>
)
}
答案 1 :(得分:0)
我在捕获此架构中的错误时没有任何问题。你在 axios 拦截器中捕获它们吗?这是我如何修改它的:
useMemo(() => {
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// Prevent infinite loops
if (
error.response.status === 401 &&
originalRequest.url === // your auth url ***
) {
handleLogout();
return Promise.reject(error);
}
if (
error.response.status === 401 &&
error.response.data.detail === "Token is invalid or expired"
) {
handleLogout(); // a function to handle logout (house keeping ... )
return Promise.reject(error);
}
if (
error.response.data.code === "token_not_valid" &&
error.response.status === 401 &&
error.response.statusText === "Unauthorized"
) {
const refreshToken = // get the refresh token from where you store
if (refreshToken && refreshToken !== "undefined") {
const tokenParts = JSON.parse(atob(refreshToken.split(".")[1]));
// exp date in token is expressed in seconds, while now() returns milliseconds:
const now = Math.ceil(Date.now() / 1000);
if (tokenParts.exp > now) {
try {
const response = await axiosInstance.post(
"***your auth url****",
{
//your refresh parameters
refresh: refreshToken,
}
);
// some internal stuff here ***
return axiosInstance(originalRequest);
} catch (err) {
console.log(err);
handleLogout();
}
} else {
console.log("Refresh token is expired", tokenParts.exp, now);
handleLogout();
}
} else {
console.log("Refresh token not available.");
handleLogout();
}
}
// specific error handling done elsewhere
return Promise.reject(error);
}
);
}, [setUser]);