我要转到特定博客文章的上一篇和下一篇文章。
考虑一下,这个盖茨比示例-https://gatsby-starter-blog-demo.netlify.com/my-second-post/
它在页面底部有2个链接-
←Hello World 是上一篇文章,新起点→是下一篇文章
要动态使用此功能,我需要访问帖子的内容,但我将如何获得它?由于使用了GraphQL,在盖兹比中很简单。
但是,在下一步中,我仅需使用preval hack即可获得帖子。我将如何获得,以便可以在自己的特定博客中实现“上一篇”和“下一篇”?
即使Next JS's own blog也没有“下一篇文章”和“上一篇文章”链接。
签出any post on Next JS's Blog,您会发现一个返回博客按钮,但没有上一个帖子或下一个帖子按钮。
答案 0 :(得分:1)
分页非常简单。您可以使用static async getInitialProps
方法从查询中获取请求的页面。
然后,您可以将button
与Router.push
一起使用进行强制路由,或者将Link
进行声明式路由。
class PaginationTest extends React.Component {
static async getInitialProps ({query: {page = 1}}) {
const data = await fetchPage(page)
return {
page: parseInt(page, 10),
data
}
}
render () {
return (
<div>
// render data
<button
onClick={() => Router.push(`/page=${this.props.page + 1}`)}
disabled={this.props.page <= 1}
>Next Button</button>
<Link href={`/page=${this.props.page + 1}`}>
<a>Next Link</a>
</Link>
</div>
)
}
}
Here is a working codesandbox: https://codesandbox.io/s/6w3k5yzqmn
答案 1 :(得分:1)
因为要生成一个静态站点,所以我假设您只关心从Next.JS的服务器端解决这个问题。为此,您基本上需要编写一个名为getNextPost(current)
的函数,该函数接收您当前的帖子(只是文件名或完整的对象),并在您的posts目录中扫描下一个帖子。对于Next.JS的服务器端,您位于Node中,因此您可以仅使用fs
包来扫描文件系统。
理想情况下,这意味着每个文件名都应带有时间戳或类似的前缀(例如2019-02-22_13-45-53-my-second-post.html
),这样您就可以使用简单的排序来确定下一个帖子是什么。否则,您实际上需要解析每个发布文件,以这种方式提取日期信息(我相信这就是盖茨比的工作方式,它肯定是雨果所做的事情。)
无论哪种方式,我建议一次将所有发布文件解析到内存缓存中,这样就不必每次都扫描发布目录。
答案 2 :(得分:0)
首先,您必须问自己“上一个帖子”和“下一个帖子”是什么意思以及如何找到这些帖子。
你能表达出来吗?回答此问题将解决您的大部分问题,而不是与Next.js相关的问题。
一旦您澄清了这一点,“我如何添加上一个和下一个帖子链接”问题的答案就是mrvdot和lipp提供的内容的组合。
创建一个getNextPost
和getPreviousPost
函数。假设您具有增量ID,一个简单(但不可靠)的示例将是:
const getPreviousPost = currentPostId => getPost(currentPostId - 1)
const getNextPost = currentPostId => getPost(currentPostId + 1)
一旦有了这些信息,就可以在“帖子”组件的getInitialProps
中查询除当前帖子之外的上一篇和下一篇帖子
class Post extends React.Component {
static async getInitialProps ({id}) {
const post = await getPost(id)
const previousPost = await getPreviousPost(id)
const nextPost = await getNextPost(id)
return {
post,
previousPost,
nextPost,
}
}
getPreviousPost = currentPostId => getPost(currentPostId - 1)
getNextPost = currentPostId => getPost(currentPostId + 1)
render ({post, previousPost, nextPost}) {
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
<Link href={previousPost.url}><a>Previous post</a></Link>
<Link href={nextPost.url}><a>Next post</a></Link>
</div>
)
}
}
或者类似的东西。这有道理吗?
答案 3 :(得分:0)
我遇到了同样的问题。我有一个函数可以获取所有帖子标题(即 slug 和 frontmatter),并且我有当前帖子的 slug。为了找到上一篇和下一篇文章,我写了这段打字稿:
export interface AdjacentPosts {
previous: { slug: string, title: string } | null,
next: { slug: string, title: string } | null,
};
export function getAdjacentPosts(slug: string): AdjacentPosts {
const allPostHeaders = getAllPostHeaders();
const postIndex = allPostHeaders.findIndex(postHeader => postHeader?.slug === slug);
return {
previous: postIndex <= 0
? null
: { slug: allPostHeaders[postIndex - 1]!.slug, title: allPostHeaders[postIndex - 1]!.frontmatter.title },
next: postIndex >= allPostHeaders.length - 1
? null
: { slug: allPostHeaders[postIndex + 1]!.slug, title: allPostHeaders[postIndex + 1]!.frontmatter.title }
};
}
我在 [slug].tsx
中使用此函数:
export const getStaticPaths: GetStaticPaths = async () => {
const slugs = getAllPostSlugs().concat(getAllPageSlugs());
return {
paths: slugs.map(slug => ({ params: { slug }, })),
fallback: false,
}
}
export const getStaticProps: GetStaticProps = async ({ params }) => {
if (!params) {
return { props: {} };
}
const post = getPostBySlug(params.slug as string)
if (post) {
return {
props: {
post,
isPost: true,
adjacentPosts: getAdjacentPosts(post.slug)
}
}
}
const page = getPageBySlug(params.slug as string)
return { props: { post: page!, isPost: false, adjacentPosts: null } };
}
export default function PostBody(props: { post: PostData, isPost: boolean, adjacentPosts: AdjacentPosts | null }) {
const { post, isPost } = props;
const previous = props.adjacentPosts?.previous;
const next = props.adjacentPosts?.next;
return (
<React.Fragment>
...the blog post itself, and then this:
<nav className="post-navigation" role="navigation" aria-label="Posts">
<h2 className="sr-only">Post navigation</h2>
<div className="grid sm:grid-cols-1 md:grid-cols-2 gap-6">
<div className="nav-previous">
{previous && (
<Link href={previous.slug}>
<a className="flex flex-col text-left" rel="prev">
<span className="text-base mb-2">Previous: </span>
<span className="sr-only">Previous post:</span>
<span className="text-primary-500 leading-6">
{previous.title}
</span>
</a>
</Link>
)}
</div>
<div className="nav-next">
{next && (
<Link href={next.slug}>
<a className="flex flex-col text-right"
rel="next">
<span className="text-base mb-2">Next: </span>
<span className="sr-only">Next post:</span>
<span className="text-primary-500 leading-6">
{next.title}
</span>
</a>
</Link>
)}
</div>
</div>
</nav>
</React.Fragment>
)
}
祝你好运!