NextJS嵌套动态路由二级路径下URL显示[slug]异常问题求助
Hey there! Let's break down why your sidebar links are showing [slug] instead of the actual value (like payments) when you're on a nested dynamic route (e.g., /docs/payments/introduction). This is a common gotcha with Next.js's dynamic routing, but it's easy to fix once you know what's going on.
The Root Cause
When you're on the second-level dynamic page (/docs/[slug]/[id]), any links that reference /docs/[slug]/faq directly won't automatically replace [slug] with the current route's slug value. Next.js needs explicit instructions to map the dynamic parameter to the actual value from the current page.
Solution 1: Pass the Current Slug to Your Links
You need to grab the active slug parameter from the current route and use it to build your links correctly. Here are two reliable ways to do this:
Option A: Use useRouter to Get the Slug
Import Next.js's useRouter hook to access the current route's query parameters, then inject the slug into your link path:
import Link from 'next/link'; import { useRouter } from 'next/router'; const Sidebar = () => { const router = useRouter(); // Get the active slug from the current route const currentSlug = router.query.slug; return ( <aside> {/* Use template literals to build the full path */} <Link href={`/docs/${currentSlug}/faq`}>FAQ</Link> {/* Or use the object syntax (safer for dynamic routes) */} <Link href={{ pathname: '/docs/[slug]/faq', query: { slug: currentSlug } }} > FAQ (Object Syntax) </Link> </aside> ); }; export default Sidebar;
Option B: Pass Slug as a Prop (Better for Static Generation)
If your pages are statically generated with getStaticProps, you can pass the slug directly from the page component to the sidebar. This avoids any hydration issues that might come from relying on useRouter alone:
- In your second-level page (
pages/docs/[slug]/[id]/index.js), pass the slug fromgetStaticPropsto the component:
import Sidebar from '../../../../components/Sidebar'; export default function DocDetailPage({ slug, docContent }) { return ( <div> <Sidebar currentSlug={slug} /> <main>{docContent}</main> </div> ); } export async function getStaticProps({ params }) { // Fetch your document content using params.slug and params.id const docContent = await fetchYourDoc(params.slug, params.id); return { props: { slug: params.slug, // Pass the slug to the page component docContent, }, }; }
- Update your Sidebar to use the passed prop:
import Link from 'next/link'; const Sidebar = ({ currentSlug }) => { return ( <aside> <Link href={`/docs/${currentSlug}/faq`}>FAQ</Link> <Link href={`/docs/${currentSlug}/troubleshooting`}>Troubleshooting</Link> </aside> ); }; export default Sidebar;
Solution 2: Verify Your getStaticPaths Setup
If you're using static generation, make sure your getStaticPaths in both the first-level ([slug]) and second-level ([id]) pages is generating all valid route combinations. This ensures Next.js pre-renders all possible paths and correctly maps dynamic parameters:
For the second-level page (pages/docs/[slug]/[id]/index.js):
export async function getStaticPaths() { // Fetch all possible slug + id pairs from your data source const allDocs = await fetchAllDocs(); const paths = allDocs.map(doc => ({ params: { slug: doc.slug, id: doc.id }, })); return { paths, fallback: false, // Use 'blocking' if you want on-demand static generation }; }
Quick Check: Avoid Relative Paths
Steer clear of relative paths like ../faq in your links—these can resolve incorrectly depending on the current route depth. Always use absolute paths with the actual slug value instead.
内容的提问来源于stack exchange,提问作者Iyobosa Jefferson

