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

Next.js路由更新时回调触发四次的原因及单次触发实现方案

问题原因及解决方法

为什么每次路由更新会触发四次console.log?

核心有两个原因:

  1. 事件监听器未正确解绑:你在router.events.on里用匿名函数包裹了handleHistoryChange,但解绑时传入的是handleHistoryChange本身。两者引用不一致,导致旧的监听器无法被移除,每次组件渲染都会新增一个监听器,累积后触发次数翻倍。
  2. Strict Mode 双重渲染:Next.js 开发环境默认开启 Strict Mode,会强制组件和钩子执行两次,进一步叠加了监听器的重复绑定,最终导致四次打印(两次绑定×两次触发)。

如何让它仅触发一次?

调整事件绑定逻辑,确保绑定和解绑使用同一个函数引用,同时优化依赖项:

const Root = ({ Component, pageProps }) => {
  // ...

  const handleHistoryChange = useCallback((url) => {
    console.log({ url });
  }, []);

  useEffect(() => {
    // 直接传入handleHistoryChange作为回调,无需匿名函数包裹
    router.events.on('beforeHistoryChange', handleHistoryChange);

    return () => {
      // 解绑时用同一个函数引用,确保能移除对应的监听器
      router.events.off('beforeHistoryChange', handleHistoryChange);
    };
  }, [router, handleHistoryChange]); // 依赖项改用router,比router.events更稳定
};

额外说明:开发环境下 Strict Mode 的双重渲染是正常行为,生产环境会自动消失。只要解绑逻辑正确,即使开发环境触发两次渲染,第二次渲染时会先执行上一次的清理函数移除旧监听器,再绑定新的,最终只会保留一个有效监听器,确保路由更新时仅触发一次打印。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:12:42