Next.js调用router.push跳转后Nav组件useEffect不触发的解决方法
问题原因
你遇到的是Next.js共享布局的正常特性:登录页和首页都复用同一个Layout组件,放在Layout里的Nav组件在客户端路由跳转(router.push)过程中不会被卸载重挂载,你给useEffect设置的是空依赖数组,只会在Nav组件首次挂载时执行一次,后续跳转自然不会触发。
而window.location.replace是整页重载,整个React应用会重新初始化,Nav组件也会重新挂载,所以useEffect会执行。
解决方案
这里提供两种常见的修复方案,按需选择即可:
方案1:监听路由变化触发状态更新
直接把路由路径作为useEffect的依赖项,每次路由跳转都会重新读取本地存储的用户信息,改造成本极低,适合小型项目。
修改Nav.jsx中的useEffect代码:
// 已经引入了useRouter,直接把router.pathname加入依赖数组 useEffect(() => { console.log('hi'); const storedUser = JSON.parse(localStorage.getItem('user')); if (storedUser) setUser(storedUser); }, [router.pathname]);
方案2:监听自定义登录状态事件(更高效)
如果不想每次路由跳转都执行冗余逻辑,可以在登录/登出操作时触发自定义事件,Nav组件监听事件更新状态,性能更好:
- 首先修改
login.jsx,存储完用户信息后触发事件:
axios.post(`/auth/login`, loginForm).then((res) => { const {data, token} = res.data; localStorage.setItem('auth_token', token); localStorage.setItem('user', JSON.stringify(data)); // 触发登录状态变化事件 window.dispatchEvent(new Event('authStateChange')); router.push('/'); })
- 再修改
Nav.jsx的useEffect,监听事件更新状态:
useEffect(() => { const updateUserInfo = () => { console.log('hi'); const storedUser = JSON.parse(localStorage.getItem('user')); setUser(storedUser || null); }; // 组件首次挂载时执行一次 updateUserInfo(); // 监听登录状态变化事件 window.addEventListener('authStateChange', updateUserInfo); // 组件卸载时清理事件监听 return () => window.removeEventListener('authStateChange', updateUserInfo); }, []);
后续登出操作清完本地存储后,也可以触发同一个authStateChange事件,Nav会自动更新为未登录状态,不需要调用router.reload()刷新页面。
内容的提问来源于stack exchange,提问作者civas88
相关产品推荐
相关产品推荐

