Next.js滚动动态更新URL出现404问题求解决方案
滚动动态更新URL解决404问题方案
1. 先搞定路由配置,不然肯定404
Next.js的路由是文件系统驱动的,你要访问/home/components/1这类路径,就得有对应的路由文件匹配,不然服务器端直接返回404。分两种路由模式配置:
用Pages Router(Next.js 12及更早)
在pages/home/components/目录下创建[id].js文件,直接复用原components.js的逻辑即可,或者简单导入:
// pages/home/components/[id].js import ComponentsPage from './components'; export default ComponentsPage; // 若组件ID是动态生成的,添加以下代码支持动态路径 export async function getStaticPaths() { return { paths: [], // 无需预生成所有路径则留空 fallback: true, }; } export async function getStaticProps({ params }) { return { props: { componentId: params.id }, // 可选:把ID传给页面组件使用 }; }
用App Router(Next.js 13+)
在app/home/components/目录下创建[id]/page.js,复用原page.js的内容:
// app/home/components/[id]/page.js import ComponentsPage from '../page'; export default function ComponentDetailPage({ params }) { return <ComponentsPage componentId={params.id} />; }
2. 修正滚动时的路由跳转逻辑
你之前的router.push用法有误,需要添加shallow: true参数,同时避免重复触发跳转:
const handleScroll = () => { const baseHeaderPositions = baseHeaderRefs.current.map((ref) => { const bounding = ref?.getBoundingClientRect(); if (!bounding) return { top: Infinity, bottom: Infinity }; return { top: bounding.top, bottom: bounding.bottom }; }); const topBaseHeaderIndex = baseHeaderPositions.findIndex( ({ top, bottom }) => top < window.innerHeight && bottom > 64, ); if (topBaseHeaderIndex >= 0) { setTopBaseHeaderIndex(topBaseHeaderIndex); const componentId = baseHeaderDataArr[topBaseHeaderIndex]?.id || ""; // 去掉当前URL末尾可能存在的ID,避免重复拼接 const currentBasePath = router.asPath.split('/').slice(0, -1).join('/'); const targetUrl = componentId ? `${currentBasePath}/${componentId}` : currentBasePath; // 仅当目标URL与当前URL不同时才跳转,防止滚动时频繁触发 if (router.asPath !== targetUrl) { router.push(targetUrl, undefined, { shallow: true }); } } }; useEffect(() => { // 添加passive:true优化滚动性能 window.addEventListener("scroll", handleScroll, { passive: true }); return () => { window.removeEventListener("scroll", handleScroll); }; }, [router, baseHeaderDataArr]);
3. 核心要点说明
- Shallow Routing的作用:
shallow: true让Next.js仅更新URL,不会重新加载页面组件,也不会触发服务器端的数据获取逻辑,完全适配滚动时的URL更新场景。 - 路由配置的必要性:即便用了shallow路由,用户刷新页面或直接访问带ID的URL时,服务器需要匹配到对应的路由,否则仍会返回404,因此动态路由文件必须创建。
- 避免重复跳转:增加URL判断逻辑,防止滚动过程中频繁调用
router.push,既优化性能也避免潜在问题。
内容的提问来源于stack exchange,提问作者Malith Dilshan
相关产品推荐
相关产品推荐

