Next.js路由事件异常:加载页面无法自动消失问题排查
解决Next.js加载提示无法自动消失的问题
在Next.js中实现页面加载提示功能时,用户导航到新页面会显示加载提示,但偶尔会出现加载提示一直停留无法消失的情况。推测是状态未正确更新或路由加载后未正确检查路径导致,尝试在useEffect依赖数组中加入router、router.asPath和router.events后问题依旧,需要解决加载提示在页面加载完成后自动消失的问题。
原代码示例
Loading组件:
import React, { useState, useEffect } from 'react' import { useRouter } from 'next/router'; export default function Loading() { const router = useRouter() const [loading, setLoading] = useState(false) useEffect(() => { const hanldeChangeStart = (url) => { url !== router.asPath && setLoading(true) } const hanldeChangeComplete = (url) => { url === router.asPath && setLoading(false) } router.events.on('routeChangeStart', hanldeChangeStart) router.events.on('routeChangeComplete', hanldeChangeComplete) router.events.on('routeChangeError', hanldeChangeComplete) return () => { router.events.off('routeChangeStart', hanldeChangeStart) router.events.off('routeChangeComplete', hanldeChangeComplete) router.events.off('routeChangeError', hanldeChangeComplete) } }) if(loading){ return ( <div className='vh-100 vw-100 text-center'> <h1>Loading...</h1> <p>{loading ? 'loading' : 'notloading'}</p> </div> ) } }
_app.js:
import Loading from '@/components/Loading'; export default function App({ Component, pageProps }) { return ( <> <Loading /> <Component {...pageProps} /> </> ) }
问题分析与修复方案
原代码存在三个核心问题:
useEffect缺少依赖数组,会导致组件每次渲染时重复绑定路由事件,引发状态更新混乱routeChangeComplete事件中通过url === router.asPath判断存在逻辑漏洞——路由完成后router.asPath已更新为目标URL,该判断可能失效- Loading组件在
loading为false时未返回任何节点,不符合React组件的渲染规范
修复后的Loading组件代码:
import React, { useState, useEffect } from 'react' import { useRouter } from 'next/router'; export default function Loading() { const router = useRouter() const [loading, setLoading] = useState(false) useEffect(() => { const handleRouteChangeStart = () => { setLoading(true) } const handleRouteChangeEnd = () => { setLoading(false) } router.events.on('routeChangeStart', handleRouteChangeStart) router.events.on('routeChangeComplete', handleRouteChangeEnd) router.events.on('routeChangeError', handleRouteChangeEnd) return () => { router.events.off('routeChangeStart', handleRouteChangeStart) router.events.off('routeChangeComplete', handleRouteChangeEnd) router.events.off('routeChangeError', handleRouteChangeEnd) } }, []) // 空依赖数组,确保仅在组件挂载时绑定一次事件 return loading ? ( <div className='vh-100 vw-100 text-center'> <h1>Loading...</h1> <p>loading</p> </div> ) : null; // loading为false时返回null,避免无意义渲染 }
修复说明
- 空依赖数组:确保
useEffect仅在组件挂载时执行一次,避免重复绑定路由事件导致的状态异常 - 简化事件逻辑:去掉冗余的URL判断,路由开始时直接设
loading为true,路由完成/出错时直接设为false,逻辑更可靠 - 统一返回值:组件始终返回一个合法节点(加载提示或
null),符合React组件渲染要求
如果需要处理同路由参数变化的场景(如动态路由/post/[id]),可在useEffect的依赖数组中加入router.asPath,并添加对应逻辑:
useEffect(() => { // 原有事件绑定逻辑... // 处理同路由参数变化 setLoading(false) }, [router.asPath])
内容的提问来源于stack exchange,提问作者Viper
相关产品推荐
相关产品推荐

