将 getStaticPaths 与动态路由一起使用

Posted

技术标签:

【中文标题】将 getStaticPaths 与动态路由一起使用【英文标题】:Usage of getStaticPaths with dynamic routes 【发布时间】:2021-09-19 23:17:45 【问题描述】:

我有一个索引页面,我按部分(热门电影、热门电影等)显示电影,为此我在 getStaticProps 中调用 不同 api url。现在在[movieId].js 页面中,我使用的是getStaticPaths,因为我使用的是动态路由。但我不明白的是用户可以点击 any 部分上的 any 电影项目,但因为我需要在[movideId].js 中获取所有可能电影的路径页面并在getStaticPaths中以paths返回,

我如何知道用户点击了哪个部分,以便我可以在 getStaticPaths 中调用该特定 api 以获取正确的数据并返回正确的路径?

这是我的代码

// index.js 

export default function Home(props) 

  return (
    <>
      <div>
        <h1>Trending</h1>
        props.trending.results.map((movie, index) => 
          return (
            <div key=index>
              <Link href=`/movie/$movie.id`>
                <a>movie.original_title</a>
              </Link>
            </div>
          );
        )
      </div>

      <div>
        <h1>Popular</h1>
        props.popular.results.map((movie, index) => 
          return (
            <div key=index>
              <Link href=`/movie/$movie.id`>
                <a>movie.original_title</a>
              </Link>
            </div>
          );
        )
      </div>
    </>
  );



export async function getStaticProps() 
  try 
    const token = '...';

    const [trendingRes, popularRes] = await Promise.all([
      fetch(
        `https://api.themoviedb.org/3/trending/movie/week?api_key=$token`
      ),
      fetch(
        `https://api.themoviedb.org/3/movie/popular?api_key=$token&language=en-US&page=1`
      )
    ]);

    const [trending, popular] = await Promise.all([
      trendingRes.json(),
      popularRes.json()
    ]);

    return  props:  trending, popular  ;
   catch (err) 
      return  notFound: true ;
  


// [movieId].js

export async function getStaticPaths() 

  const token = "...";
  const res = await fetch(
    `https://api.themoviedb.org/3/trending/movie/week?api_key=$token` // here I am hardcoding to call trending api url no matter which section a user has clicked on 
  );
  const data = await res.json();

  return 
    paths: data.results.map((d) => ( params:  movieId: d.id.toString()  ))
  ;

Full Code sample

现在如果用户点击popular 部分的电影,它会显示 404 not found 页面,因为我只有来自趋势 api url 的数据和路径。

我还在学习 nextjs,所以希望我的解释可以理解,请随意询问有关此的更多详细信息。

【问题讨论】:

【参考方案1】:

在现实生活中,如果您拥有大型数据集,您不会希望预渲染所有可能的组合和所有可能的电影页面。

幸运的是,getStaticPaths 有一个 fallback 标志。

你可以使用fallback: blocking(docs),这样如果页面的key没有在getStaticPaths中指定,页面将在第一次请求后生成(并缓存)。但是您需要一个 api,您可以在其中按 id 获取电影。你有它,所以你需要做的就是改变fallback 键。 Check this Stackblitz example

如果您没有这样的 api,您可以例如拆分您的路线并拥有 /trending/[id] 路线和 popular/[id] 路线。这样您就可以始终知道需要从哪里获取电影。

希望它有意义,请随时提出其他问题。

【讨论】:

您提到if you have large data set you would not want to prerender all the possible combinations and all possible movie pages.,这是否意味着最好按照您的建议拆分路线并使用不同的路线以获得更好的实践? 不,我的意思是,如果你有 10 万部电影,那么你不想在构建时制作 10 万个预渲染页面,那将是愚蠢的。 哦,我明白了。谢谢,我会记住这一点的。【参考方案2】:

鉴于您提到的示例,我不会使用getStaticPaths,而是使用getServerSideProps,因为getStaticPaths 用例仅适用于您想要静态生成少量页面的情况。

getServerSideProps 中,您将可以访问context 对象。然后,访问context.query 将获得您页面的动态路径包含的任何内容。

举个例子:

在 Next.js 项目的 pages 文件夹中,创建一个名为 movies 的文件夹,然后在其中创建一个 [id].js

这将匹配以下路径:

/movies/1
/movies/123
/movies/456

然后您可以使用动态路径(即123)调用您的 API 并获取特定电影。

【讨论】:

以上是关于将 getStaticPaths 与动态路由一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Next.js 中设置多语言环境动态页面的 getStaticPaths

Next.js 动态路由错误:提供的路径 `page-name` 与页面不匹配:`/[slug]`

错误:动态 SSG 页面需要 getStaticPaths,而“xxx”缺少 getStaticPaths。 NextJS

是否可以使用 API 路由在 Next.JS getStaticProps/getStaticPaths 中构建页面? [复制]

如何让 Next JS 动态路由与 RelayJS 一起使用

如何不在 Next.js 动态路由之间保持状态?