You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js13电商站点动态路由问题:单路径匹配分类/集合slug

解决Next.js App Router中分类/集合共享slug路径的404问题

你的核心问题是同一个/products/{slug}路径会同时触发路由组里的两个page.tsx,其中必然有一个会因为找不到对应数据抛出notFound(),导致页面报错。下面是直接可行的解决方案:

1. 调整路由结构

删除(collections)和(categories)两个路由组,合并成单个page.tsx,最终结构如下:

products /
  [slug] /
    layout.tsx
    page.tsx

2. 统一处理slug匹配逻辑

在新的page.tsx中,先尝试匹配分类数据,失败后再匹配集合数据,两者都匹配失败才抛出notFound():

import { notFound } from 'next/navigation';
import ProductList from '@/components/ProductList';
import FilterSidebar from '@/components/FilterSidebar';

// 封装统一的slug查询函数
async function resolveSlug(slug: string) {
  // 优先查询分类
  const category = await getCategoryProducts(slug);
  if (category) return { type: 'category', data: category };

  // 分类不存在则查询集合
  const collection = await getCollectionProducts(slug);
  if (collection) return { type: 'collection', data: collection };

  // 两者都不存在返回null
  return null;
}

export default async function ProductPage({ params }: { params: { slug: string } }) {
  const resolvedData = await resolveSlug(params.slug);

  if (!resolvedData) {
    notFound();
  }

  return (
    <div className="product-page">
      <h1>
        {resolvedData.type === 'category' 
          ? `分类:${resolvedData.data.name}` 
          : `集合:${resolvedData.data.name}`}
      </h1>
      {/* 渲染商品列表 */}
      <ProductList products={resolvedData.data.products} />
      {/* 渲染全局筛选组件(包含所有分类和集合选项) */}
      <FilterSidebar />
    </div>
  );
}

3. 处理静态生成(generateStaticParams)

如果需要静态生成页面,并行获取所有分类和集合的slug,合并后返回即可:

export async function generateStaticParams() {
  // 并行请求分类和集合的slug列表
  const [categorySlugs, collectionSlugs] = await Promise.all([
    getAllCategorySlugs(), // 需返回形如 [{ slug: 'electronics' }, ...] 的数组
    getAllCollectionSlugs() // 需返回形如 [{ slug: 'summer-sale' }, ...] 的数组
  ]);

  // 合并并去重(如果后端保证slug唯一可省去去重步骤)
  const uniqueSlugs = Array.from(
    new Set([...categorySlugs, ...collectionSlugs].map(item => item.slug))
  ).map(slug => ({ slug }));

  return uniqueSlugs;
}

注意事项

  • 确保后端分类和集合的slug不重复,否则会出现优先级问题(先查询到的类型会被返回)。
  • 可以在layout.tsx中渲染公共的筛选栏组件,展示所有可用的分类和集合选项,无需在每个子页面重复实现。

内容的提问来源于stack exchange,提问作者Jonathan Franzen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:42:24