如何让Next.js示例中的router.push在登录接口返回200后正常工作?
看起来你遇到了个挺闹心的问题:明明登录接口返回200,日志也正常打印了,但路由就是纹丝不动,连个报错信息都没有。我来帮你梳理几个常见的排查方向和解决办法:
1. 检查是否混用了Pages Router和App Router的useRouter
这是Next.js 13+版本里非常容易踩的坑!如果你的项目是App Router结构(有app/目录),但你导入的是next/router的useRouter,那这个API根本不会生效——App Router对应的路由API是next/navigation里的useRouter。
修改导入语句试试:
// 替换原来的导入 import { useRouter } from 'next/navigation'
如果你的项目是传统的Pages Router(只有pages/目录),这条可以跳过,但还是建议确认下Next.js版本和路由模式是否匹配。
2. 捕获router.push的异步错误
router.push其实是异步函数,虽然你没看到控制台报错,但可能存在未被捕获的异常。试试用try/catch包裹跳转逻辑,同时等待跳转完成:
if (response.status === 200) { console.log('pushing editor'); try { const jumpResult = await router.push("/editor"); console.log('跳转结果:', jumpResult); // 成功的话会返回undefined或目标URL } catch (err) { console.error('跳转过程出错:', err); } console.log(router) }
这样能帮你揪出那些隐藏的错误,比如路由配置错误、目标页面不存在之类的问题。
3. 检查是否有中间件(Middleware)拦截了跳转
如果你的项目里有middleware.ts/middleware.js,大概率是中间件的认证逻辑拦截了跳转。因为fetch请求返回200后,浏览器的Cookie可能还没来得及更新,这时候触发router.push,中间件检查Cookie时还是旧的未登录状态,就会把页面重定向回登录页,看起来像是没跳转。
解决办法:
- 先等待接口返回的响应体处理完成,确保Cookie已经写入:
if (response.status === 200) { await response.json(); // 等待响应体解析完成,确保Cookie生效 console.log('pushing editor'); await router.push("/editor"); }
- 或者检查
middleware.ts里的逻辑,确认是否对/editor的跳转做了正确的认证判断。
4. 监听路由事件排查状态
给路由添加事件监听,看看跳转到底有没有触发,或者哪里出了问题:
import { useRouter } from 'next/router' // 或者next/navigation,根据你的路由模式 import { useEffect } from 'react'; export default function Login() { const router = useRouter(); useEffect(() => { // 监听路由变化事件 const handleRouteStart = (url) => console.log('开始跳转到:', url); const handleRouteComplete = (url) => console.log('成功跳转到:', url); const handleRouteError = (err, url) => console.error('跳转失败:', err, '目标:', url); // Pages Router的事件监听方式 if ('events' in router) { router.events.on('routeChangeStart', handleRouteStart); router.events.on('routeChangeComplete', handleRouteComplete); router.events.on('routeChangeError', handleRouteError); } return () => { // 清理事件监听 if ('events' in router) { router.events.off('routeChangeStart', handleRouteStart); router.events.off('routeChangeComplete', handleRouteComplete); router.events.off('routeChangeError', handleRouteError); } }; }, [router]); // 其他代码... }
通过这些日志,你能清楚看到路由跳转的各个阶段状态,判断是没触发跳转,还是触发后被拦截了。
5. 临时移除prefetch试试
你在useEffect里做了router.prefetch("/editor"),虽然prefetch本身是预加载,理论上不影响跳转,但也不排除某些特殊场景下预加载导致的冲突。可以先注释掉这部分代码,看看跳转是否恢复正常:
// useEffect(() => { // router.prefetch("/editor") // }, [])
先从这几个方向排查,应该能找到问题所在!
内容的提问来源于stack exchange,提问作者saq7

