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

NextJS动态路由参数变化后getStaticProps未触发如何解决?

问题根源

你当前使用的是Next.js Pages Router的纯静态生成(SSG)模式,getStaticProps仅在项目构建阶段执行一次,同个动态路由模板(/pages/[category]/index.tsx)的客户端路由跳转时,Next.js会复用已加载的页面组件实例,不会重新触发getStaticProps拉取新数据,因此只有刷新页面时才会请求服务器拿到对应分类的静态页面数据。

解决方案

方案1:替换为getServerSideProps(最推荐,改造成本最低)

直接将静态生成改为服务端渲染,每次请求(包括客户端路由跳转)都会重新执行服务端逻辑拉取对应分类的数据,完全符合你的需求。

  1. 删除现有getStaticPaths代码,getServerSideProps不需要预先生成路径
  2. 将getStaticProps替换为如下代码:
export const getServerSideProps: GetServerSideProps = async (context) => {
    const category = context.params?.category as string || "";
    const productsData = await getPaginatedProducts(1, category);
    const envPag = process.env.pagination || '0';
    const totalPages = Math.ceil(productsData.total / parseInt(envPag));

    return {
        props: {
            products: productsData.items,
            totalPages,
            currentPage: 1
        },
    }
}
  • 优点:代码改动量极小,不需要调整组件逻辑,数据永远和服务端同步
  • 缺点:响应速度比纯SSG稍慢,对分类页这类场景几乎感知不到差异

方案2:保留SSG,监听路由变化手动拉取数据

如果需要保留SSG的首屏加载速度优势,可以在组件内监听分类参数变化,手动触发数据拉取更新本地状态。

  1. 给getStaticProps添加revalidate配置开启增量静态再生,保证构建后的数据可更新:
export const getStaticProps: GetStaticProps = async (context) => {
    const category = context.params?.category || "";
    const productsData = await getPaginatedProducts(1, category);
    const envPag = process.env.pagination || '0';
    const totalPages = Math.ceil(productsData.total / parseInt(envPag));

    return {
        props: {
            products: productsData.items,
            totalPages,
            currentPage: 1
        },
        revalidate: 60 // 单位为秒,可根据业务需求调整缓存时间
    }
}
  1. 调整页面组件逻辑,添加状态管理和路由监听:
// 新增导入
import { useState, useEffect } from 'react'

export default function ProductsIndex(props: ProductsIndexProps) {
    const router = useRouter();
    // 新增本地状态存储页面数据
    const [products, setProducts] = useState<ProductItemModel[]>(props.products);
    const [totalPages, setTotalPages] = useState(props.totalPages);
    const [currentPage, setCurrentPage] = useState(props.currentPage);

    // 监听分类参数变化,拉取对应分类数据
    useEffect(() => {
        if (!router.isReady) return;
        const category = router.query.category as string || "";
        const fetchCategoryData = async () => {
            const productsData = await getPaginatedProducts(1, category);
            // 注意前端访问的环境变量需要添加NEXT_PUBLIC_前缀
            const envPag = process.env.NEXT_PUBLIC_pagination || '0';
            const total = Math.ceil(productsData.total / parseInt(envPag));
            setProducts(productsData.items);
            setTotalPages(total);
            setCurrentPage(1);
        }
        fetchCategoryData();
    }, [router.query.category, router.isReady])

    return (
        <div>
            <div className={styles.title_section}>
                <h2 className={styles.title}>Results for all items</h2>
            </div>

            <div className={styles.list_container}>
                <section className={styles.list_sidebar}></section>
                <ProductList
                    products={products}
                    category={asString(router.query.category || "") || ""}
                    currentPage={currentPage}
                    totalPages={totalPages}
                />
            </div>
        </div>
    );
}
  • 优点:首屏保留SSG的高性能,客户端跳转体验流畅
  • 缺点:需要额外编写状态逻辑,若getPaginatedProducts依赖仅服务端可访问的Contentful密钥,需要额外封装前端可调用的接口层

方案3:跳转时强制刷新页面(不推荐)

在分类跳转的链接上使用原生页面跳转代替Next.js客户端路由,每次跳转都会重新请求页面资源拉取对应数据,但会丢失单页应用的流畅跳转体验,仅适合临时调试使用。


内容的提问来源于stack exchange,提问作者Daniel Molnar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:30:01