NextJS 13 App目录下Axios拦截器跳转失效问题求助
NextJS 13中Axios拦截器的跳转问题及解决思路
有人找到在NextJS 13中使用Axios拦截器的解决方案吗?我本以为这应该很简单,但实际并非如此。
客户端组件代码
"use client" import React, { useState } from 'react' import axiosInterceptorInstance from '@/lib/request' interface Device { // 设备字段定义 } export default function DevicesHolder() { const [devices, setDevices] = useState<Device[]>([]) axiosInterceptorInstance.get('/api/v1/staff-admin/devices?page=1&itemsPerPage=20').then((res) => { setDevices(res.data.data) }) return ( <> {devices.map((device, key) => ( <div key={key}> <h1>{device.imei}</h1> </div> ))} </> ) }
Axios拦截器代码
import axios from "axios"; import { redirect } from 'next/navigation' const axiosInterceptorInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL, // 替换为你的API基础地址 }); axiosInterceptorInstance.interceptors.response.use( (response) => { // 在这里修改响应数据 return response; }, (error) => { // 处理响应错误 // 如果未授权,跳转到登录页 console.log("server", typeof window === 'undefined') if (error.response.status === 401) { redirect('/login') } return Promise.reject(error); } ); export default axiosInterceptorInstance;
问题描述
不知为何,请求会同时在服务端和客户端执行,且两端都无法完成跳转,还抛出了NEXT_REDIRECT错误(这是预期行为吗?)。有没有解决思路?
补充说明:我曾尝试使用window.location.href,但显然在服务端执行时会报错。
解决思路
1. 区分服务端与客户端环境处理跳转
NextJS 13的客户端组件在SSR/SSG阶段会在服务端执行一次,此时调用redirect()会抛出NEXT_REDIRECT错误(这是框架预期行为),而服务端环境下window对象不存在,直接用window.location.href会报错。修改拦截器的错误处理逻辑,分别适配两端:
import axios from "axios"; import { redirect } from 'next/navigation' const axiosInterceptorInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL, }); axiosInterceptorInstance.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // 客户端环境用window跳转 if (typeof window !== 'undefined') { window.location.href = '/login'; } else { // 服务端环境抛出redirect,让NextJS自动处理服务端跳转 redirect('/login'); } } return Promise.reject(error); } ); export default axiosInterceptorInstance;
2. 避免服务端发起不必要请求
原组件在顶层直接发起请求,会导致SSR阶段服务端也执行一次请求。将请求放到useEffect中,确保仅在客户端执行:
"use client" import React, { useState, useEffect } from 'react' import axiosInterceptorInstance from '@/lib/request' import { isRedirectError } from 'next/dist/client/components/redirect' interface Device { imei: string; // 其他字段 } export default function DevicesHolder() { const [devices, setDevices] = useState<Device[]>([]) useEffect(() => { const fetchDevices = async () => { try { const res = await axiosInterceptorInstance.get('/api/v1/staff-admin/devices?page=1&itemsPerPage=20') setDevices(res.data.data) } catch (err) { // 不要捕获NEXT_REDIRECT错误,让框架处理跳转 if (!isRedirectError(err)) { // 处理其他业务错误,比如提示用户 console.error('获取设备列表失败:', err) } } } fetchDevices() }, []) return ( <> {devices.map((device, key) => ( <div key={key}> <h1>{device.imei}</h1> </div> ))} </> ) }
3. 正确处理服务端跳转的NEXT_REDIRECT错误
服务端调用redirect()抛出的NEXT_REDIRECT错误是NextJS的预期行为,框架会自动捕获并完成跳转,无需手动处理。如果在请求中用try/catch包裹,注意不要捕获该错误,或者判断后重新抛出,避免阻止跳转。
内容的提问来源于stack exchange,提问作者LUKER
相关产品推荐
相关产品推荐

