Next.js 12.3.0使用router.push()偶现浏览器标签页冻结问题求助
Next.js 12.3.0 同页跳转偶尔导致标签页冻结问题
使用Next.js 12.3.0时,点击按钮调用API接口后,通过router.push()跳转至当前页面,该操作85%的情况下正常,但偶尔会出现浏览器标签页完全冻结,无法进行任何操作,只能关闭标签页。浏览器控制台与终端均无报错,应用其他功能正常。已排查无无限渲染或循环问题,当前开启了StrictMode,连续点击按钮8-9次后易触发该问题,怀疑与getServerSideProps被多次调用有关。
相关版本信息
"next": "12.3.0",
按钮点击逻辑代码
<Button onClick={async() => { await axios .patch('url', updateTrackDto) .then((res) => { router.push(`/tracks`); // 跳转至当前页面路径 }).catch((error) => { console.log(error); }); }>update</Button>
getServerSideProps代码
export async function getServerSideProps(context) { const trackId = context.params.trackId; const track = await axios.get(`http://127.0.0.1:5000/track/get/${trackId}`); return { props: { track: track.data, }, }; }
排查方向与解决方案
1. 阻止重复请求与跳转堆积
连续点击按钮会触发多次API请求和页面跳转,导致客户端与服务端请求堆积,阻塞主线程。给按钮添加点击禁用状态,在请求完成前禁止重复操作:
const [isLoading, setIsLoading] = useState(false); <Button onClick={async() => { if (isLoading) return; setIsLoading(true); try { await axios.patch('url', updateTrackDto); router.push(`/tracks`); } catch (error) { console.log(error); } finally { setIsLoading(false); } }} disabled={isLoading} > {isLoading ? '更新中...' : 'update'} </Button>
2. 优化同页跳转逻辑
使用router.push跳转当前页面时,Next.js会重新触发getServerSideProps,多次连续触发可能导致服务端请求排队,进而阻塞客户端渲染:
- 若仅需刷新数据,直接在API请求成功后重新获取数据并更新本地状态,避免页面跳转:
// 组件内维护track状态 const [track, setTrack] = useState(props.track); // 点击逻辑中替换跳转为状态更新 await axios.patch('url', updateTrackDto); const freshTrack = await axios.get(`http://127.0.0.1:5000/track/get/${trackId}`); setTrack(freshTrack.data); - 若必须跳转,添加
shallow: true参数减少不必要的服务端请求(getServerSideProps仍会执行,但仅更新客户端路由):router.push(`/tracks`, undefined, { shallow: true });
3. 处理StrictMode的重复调用影响
StrictMode在开发环境下会重复调用getServerSideProps等数据获取方法,可能加剧请求堆积。可临时关闭StrictMode验证问题是否消失,但更推荐从请求控制层面解决,而非长期关闭StrictMode。
4. 给服务端请求添加超时
getServerSideProps中的axios请求未设置超时,若服务端响应缓慢,多次请求会占用资源。添加超时配置避免请求长时间阻塞:
const track = await axios.get(`http://127.0.0.1:5000/track/get/${trackId}`, { timeout: 5000 // 设置5秒超时 });
内容的提问来源于stack exchange,提问作者Ahmed Sbai
相关产品推荐
相关产品推荐

