嗨,这是 Axios 的下一个 js 应用程序,TanstackQuery。我正在尝试重新路由到“/login”页面,以防 AxiosInterCeptorIntance 捕获 401。 React 版本 18、react-dom 版本 18、React 14.1.3
使用
useRouter
的
next/navigation
会引发错误
import axios from "axios";
import { RedirectType, redirect, useRouter } from "next/navigation";
import toast from "react-hot-toast";
const AxiosInterceptorInstance = () => {
const router = useRouter();
const axiosInterceptorInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
});
// Request interceptor
axiosInterceptorInstance.interceptors.request.use(
(config) => {
const accessToken = localStorage.getItem("auth_token");
if (accessToken) {
if (config.headers)
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
// Response interceptor
axiosInterceptorInstance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
switch (error.response.status) {
case 401:
toast.error(`${error.response.data.message}`, {
duration: 4500,
});
router.push("/login");
break;
case 422:
toast.error(`${error.response.data.errors[0]}`, {
duration: 2500,
});
break;
case 500:
toast.error("something went wrong", {
duration: 2500,
});
break;
default:
toast.error(`${error.response.statusText} | ${error.message}`);
break;
}
return Promise.reject(error);
},
);
return { axiosInterceptorInstance };
};
export default AxiosInterceptorInstance;
您不能在 React hooks 或 React 组件之外使用 hooks。
您可以使用事件总线来发出路由器,例如:
// event-bus.ts
import type { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';
import eventemitter from 'eventemitter3';
export const eventBus = eventemitter();
export const push = (path: string) => {
eventBus.emit('router-push', path);
}
export const subscribe = (router: AppRouterInstance) => {
const onPush = (path: string) => {
router.push(path);
}
eventBus.on('router-push', onPush);
return () => {
eventBus.off('router-push', onPush);
}
}
'use client'
// Create SetupRouterListener.tsx
// Then add this component to your Layout.tsx
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
import { eventBus, subscribe } from './event-bus';
export default function SetupRouterListener() {
const router = useRouter();
useEffect(() => {
return subscribe(router);
}, [router]);
return null
}
终于有了一些改进:
import axios from "axios";
import toast from "react-hot-toast";
import { push } from './event-bus';
const isBrowser = typeof document !== 'undefined';
const AxiosInterceptorInstance = () => {
const axiosInterceptorInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
});
// Request interceptor
axiosInterceptorInstance.interceptors.request.use(
(config) => {
const accessToken = isBrowser ? localStorage.getItem("auth_token") : '';
if (accessToken) {
if (config.headers)
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
// Response interceptor
axiosInterceptorInstance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
switch (error.response.status) {
case 401:
toast.error(`${error.response.data.message}`, {
duration: 4500,
});
push("/login");
break;
case 422:
toast.error(`${error.response.data.errors[0]}`, {
duration: 2500,
});
break;
case 500:
toast.error("something went wrong", {
duration: 2500,
});
break;
default:
toast.error(`${error.response.statusText} | ${error.message}`);
break;
}
return Promise.reject(error);
},
);
return { axiosInterceptorInstance };
};
export default AxiosInterceptorInstance;