【问题标题】:Server Side Render Dynamic Page based on Route Param基于路由参数的服务器端渲染动态页面
【发布时间】:2020-09-13 11:24:39
【问题描述】:

我从 Next.js 开始,在浏览文档后,我无法弄清楚如何在 getStaticPaths 方法中获取路由参数 code,如下所示!?。 code 以任何方式事先都不知道,它可以是任何东西。

我不想调用 api 并在组件内部使用 useEffect 获取数据。

文件:pages/post/[code].js

import React from 'react';
import apiCall from 'api/something';

export default ({post}) => {
     return <>
        render components here based on prop `post`
    </>
}

export async function getStaticPaths() {
    // How to get [code] from the route here, which can be used below?
    return { 
        paths: // NEED [code] HERE from current route,
        fallback: false
    }
} 

export async function getStaticProps(ctx) {
    return {
        props: { 
         // [ctx.code] resolved from current route with the help of getStaticPaths,
         post: apiCall(ctx.code) 
        }
    }
}

我试过 getServerSideProps 对我有用:

export const getServerSideProps = async (ctx) => {
    return {
        props: {
            post: await apiCall(ctx.query.code)
        }
    };
};

但是当我做next export 声明时它失败了:

无法导出带有getServerSideProps 的页面。在此处查看更多信息:https://err.sh/next.js/gssp-export

在进一步调查此错误I found this solution 后,这对我来说是不可行的,因为我的应用托管在 Heroku 上。

我正在尝试根据路由参数code 在服务器端渲染 html 以及数据。但现在做不到。

【问题讨论】:

  • 你没有在 getStaticProps 中得到 ctx.code 吗??
  • @pritesh 我使用了getServerSideProps,但在next export 上失败了

标签: javascript reactjs next.js server-side-rendering


【解决方案1】:

据我了解,您希望在构建时静态生成动态路由。

为此,您需要通过指定所有 codes 来让 Next.js 知道要生成哪些页面。

export async function getStaticPaths() {
    // you don't need here a code from current route
    // but you need to specify all known post codes
    return { 
        paths: [
          { params: { code: '1' } },
          { params: { code: '2' } },
          { params: { code: '3' } },
        ]
        fallback: false
    }
}

每次更改帖子时,您都需要重新构建应用程序。

如果您不想每次都重新构建项目,请使用getServerSideProps。然后将在请求时获取数据。你不能 export 它,因为它需要 Node.js 服务器。

【讨论】:

  • 如何在 Next.js 之上实现 Node.js 服务器,并使其导出 SSR 构建?
  • @boop_the_snoot,您可以在 Node.js 环境中运行 Next.js 内置服务器 - 参见 nextjs.org/docs/deployment#nodejs-server。您无法导出 SSR 构建,因为服务器端渲染需要服务器。
【解决方案2】:

函数getStaticPaths 的目的是生成一个路径列表,在构建时将为其呈现静态HTML。例如,对于 10 个帖子的列表,如果您知道帖子的 id,则可以提前生成 10 个posts/[id] 路由。

getStaticPaths 如何处理动态路由的详细信息..

假设您有一个动态路由/posts/[postId],如果您选择使用静态生成,则必须生成一个路径列表,其中将包含postId 作为路由参数,并且对于返回的每个路径,函数getStaticProps将在构建时调用以查询数据。例如,

// for /post/[postId]

export const getStaticPaths = async () => {
  // if you know all the postId ahead of time

  const paths = [
     { params: { postId: '1234' } },  // keep in mind postId has to be a string
     { params: { postId: '3792' } },
     { params: { postId: '1749' } },
  ]

  return {
    paths,
    fallback: false // we are disabling fallback because we know all the paths ahead of time
  }
}

// for each path returned getStaticProps will be called at build time
export const getStaticProps = async (context) => {
   // you have access to the postId params that you returns from
   // getStaticPaths here
   const postId = context.params.postId 

   // now you can query the data from postId and return as props

   return {
     props: // queried data
   }
}

如果 fallback 设置为 false any 对于任何未从函数 getStaticPaths 返回的路由路径,nextjs 将仅显示 404 错误页面。

如何使用fallback: true为事先未知的路由参数生成静态页面

如果您知道一些postId 的帖子并且posts 的数据不经常更改,您可以选择生成将fallback 属性设置为true 的页面,这将显示一个回退不是从函数getStaticPaths 返回的路径的页面版本。在请求页面时,nextjs 将调用getStaticProps 并将数据作为 JSON 发送,该数据将用于在浏览器中呈现页面。 例如,

// for /post/[postId]
export const getStaticPaths = async () => {
   // you can get how many ever postIds are know ahead of time 
   // and return as paths with fallback set to true
   const posts = // queried data from db or fetched from remote API

   const paths = posts.map(post => { params:{ postId: post.id.toString() }})

   return {
      paths,
      fallback: true
   }

}

// in your page Component check for fallback and render a loading indicator
import { useRouter } from 'next/router';

const MyPage = (props) => {
  // before you do anything
  const router = useRouter();

  if (router.isFallback) {
    return <div>Loading....</div>
  }

  // rest of your page logic

}

如果您的数据非常动态,假设每 30 分钟或一个小时左右更改一次。您可以选择使用服务器端渲染,这将在每个请求的基础上fetch 数据,但 TTFB(到第一个字节的时间)会更高。例如,

// for /post/[postId]
export const getServerSideProps = async (context) => {

  // you also have access to the param postId from the context
  const postId = context.params.postId

  // query the data based on the postId and return as props
  return {
    props: // queried data
  }  

}

请记住,如果您选择使用 getServerSideProps,该函数将在每个请求的基础上被调用,因此第一个字节的时间会更长。

根据用例,您还可以使用来自 nextjs 团队 repo linkswr 使用静态生成和客户端数据获取。

【讨论】:

  • 正如问题本身所述,我需要利用getServerSideProps 功能,但在导出下一个应用程序时会抛出this error。请再次彻底检查我的问题。
  • 我知道您需要next export,但在使用getServerSideProps 时会失败。当您从页面导出getServerSideProps 时,“下一个导出”总是会失败,因为函数getServerSideProps 需要nodejs 服务器才能运行。这就是为什么我建议如果您没有增量数据要求,您可以使用getStaticPaths 并将fallback 设置为true。在您的next.config.js 中使用getInitialPropsexportPathMap 可能还有另一种解决方案,我认为这不是一个好的解决方案。
  • 真诚感谢您的回答。对此的后续问题是:如果我总共有 3 篇文章,id => 1,2,3 对于其中 2 篇文章,我需要使用静态生成。 => 对于 id 1,2 但对于剩下的一篇文章 => id = 3 ,我需要使用服务器端渲染 :) 如何做到这一点。
  • 对于我发表的评论,需要做回退:文档中提到的阻塞。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 2015-04-19
相关资源
最近更新 更多