Next.js Link触发Loading initial props cancelled错误,求优雅解决方案
解决Next.js重复点击Link触发
Loading initial props cancelled错误 问题原因
快速重复点击同一Next.js Link时,新的路由跳转请求会中断正在进行的页面初始props加载流程,从而抛出Error: Loading initial props cancelled错误。你当前使用useState控制加载状态的方案存在缺陷:useState的更新是异步的,快速点击时无法及时拦截重复请求。
优雅解决方案
方案一:使用useRef维护跳转状态(快速实现)
利用useRef的同步更新特性,结合Next.js Router的事件监听,精准控制跳转状态:
// navbar.ts import { useRouter } from 'next/router'; import { useRef, useEffect } from 'react'; import Link from 'next/link'; const Navbar = () => { const router = useRouter(); // 存储当前是否正在路由跳转的状态 const isNavigating = useRef(false); useEffect(() => { // 路由开始跳转时标记状态 const handleRouteStart = () => { isNavigating.current = true; }; // 路由完成/出错时重置状态 const handleRouteEnd = () => { isNavigating.current = false; }; router.events.on('routeChangeStart', handleRouteStart); router.events.on('routeChangeComplete', handleRouteEnd); router.events.on('routeChangeError', handleRouteEnd); // 组件卸载时移除事件监听 return () => { router.events.off('routeChangeStart', handleRouteStart); router.events.off('routeChangeComplete', handleRouteEnd); router.events.off('routeChangeError', handleRouteEnd); }; }, [router]); const handleLinkClick = (e: React.MouseEvent, targetPath: string) => { // 正在跳转或已在目标页面时,阻止默认跳转行为 if (isNavigating.current || router.asPath === targetPath) { e.preventDefault(); return; } }; return ( <nav> <Link href="/example" onClick={(e) => handleLinkClick(e, '/example')} > Go to Example </Link> {/* 其他Link复用相同逻辑 */} </nav> ); }; export default Navbar;
方案二:封装自定义Link组件(高复用性)
将重复点击拦截逻辑封装成通用组件,项目中所有Link统一替换,避免重复代码:
// components/CustomLink.tsx import { useRouter } from 'next/router'; import { useRef, useEffect } from 'react'; import Link, { LinkProps } from 'next/link'; const CustomLink = ({ href, children, ...props }: LinkProps) => { const router = useRouter(); const isNavigating = useRef(false); useEffect(() => { const handleStart = () => (isNavigating.current = true); const handleEnd = () => (isNavigating.current = false); router.events.on('routeChangeStart', handleStart); router.events.on('routeChangeComplete', handleEnd); router.events.on('routeChangeError', handleEnd); return () => { router.events.off('routeChangeStart', handleStart); router.events.off('routeChangeComplete', handleEnd); router.events.off('routeChangeError', handleEnd); }; }, [router]); const handleClick = (e: React.MouseEvent) => { if (isNavigating.current || router.asPath === href) { e.preventDefault(); } }; return ( <Link href={href} onClick={handleClick} {...props}> {children} </Link> ); }; export default CustomLink;
使用时直接替换原生Link:
// navbar.ts import CustomLink from '@/components/CustomLink'; const Navbar = () => { return ( <nav> <CustomLink href="/example">Go to Example</CustomLink> {/* 其他页面链接直接使用CustomLink */} </nav> ); };
补充说明
该问题在Next.js 12及13版本中均存在,官方暂未完全修复上述场景。上述方案通过拦截重复的跳转请求,从根源上避免了加载流程被中断的情况,同时保证了用户操作的流畅性。
内容的提问来源于stack exchange,提问作者Alexander Kolarov
相关产品推荐
相关产品推荐

