You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js使用shallow routing导致页面导航按钮/链接失效

问题根本原因

核心bug是你的shallow路由更新逻辑写在了无依赖数组的useEffect中:

useEffect(() => {
    router.push(`/card/${card?.id}`, undefined, { shallow: true })
});

React中不传第二个依赖参数的useEffect,会在组件每一次渲染完成后全量执行,这就直接触发了无限循环:

  1. 页面首次加载 → 执行shallow push更新URL
  2. 路由状态变化触发组件重渲染 → 再次执行shallow push
  3. 循环往复,Next.js的路由事件队列被持续的同页面shallow更新占满
  4. 点击首页按钮触发的跨页导航请求,会被不断插队的同页面路由更新反复打断、覆盖,完全无法执行,哪怕换成Link组件、手写onClick自定义导航逻辑也没用——路由实例始终处于“处理当前页shallow更新”的状态,根本不会响应跨页跳转。

你用原生window.history.pushState能临时绕过问题,本质是因为这个原生API不会触发Next.js路由状态更新、不会触发组件重渲染,自然不会形成死循环,但这种写法完全绕过了Next的路由系统,确实存在状态不同步的潜在风险。


修复方案

给useEffect加上正确的依赖数组,同时增加判断逻辑,保证URL更新仅在card.id实际变化、且当前URL和目标ID不一致时才执行,从根源切断无限循环:

useEffect(() => {
  // 避免card为空、或URL已经匹配当前卡片ID时重复触发路由更新
  if (card?.id && router.query.id !== String(card.id)) {
    router.push(`/card/${card.id}`, undefined, { shallow: true })
  }
// 仅在卡片ID、路由实例、路由参数变化时才执行effect
}, [card?.id, router, router.query.id]);

修改后无限路由更新的死循环会直接消失,首页按钮、其他所有页面导航功能都会恢复正常。


额外可优化的点

  • 不要直接修改props传入的card对象:原代码中if (card !== null) { card.dateUsed = used.toDate() }属于React反模式,props是只读的,直接修改不会触发稳定的组件重渲染,还会导致状态不可预测。建议用useState初始化card数据,接口请求成功后通过setState方法更新视图。
  • Prisma的Date类型序列化不需要用JSON.parse(JSON.stringify(card))这种hack写法,可以在返回props时手动把Date转成ISO字符串,或者用常规序列化工具处理即可,性能更好也更易维护。

内容的提问来源于stack exchange,提问作者Graham Charles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:57:31