WOF Tech Blog

Next.jsで前の記事・次の記事へのリンクを作る

Next.jsで投稿した記事の下部に前の記事・次の記事へのリンクを作成する際のメモ。

仕上がりのイメージ

pagelinks

日付でソートされた全記事の配列を作成

[slug].js
(snip)
export const getStaticProps = async ({ params }) => {
const dataDir = "data";
const fileNames = fs.readdirSync(dataDir);
const posts = fileNames
.map((fileName) => {
const postPath = path.join(dataDir, fileName);
const file = matter.read(postPath);
return {
slug: fileName.replace(/\.md$/, ""),
date: file.data.date,
};
})
.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
const slugs = [];
posts.map((post) => {
slugs.push(post.slug);
});
(snip)
return {
props: {
post: {
title: post.title,
date: post.date,
mdxSource,
slug: params.slug,
slugs: slugs
},
},
};
};
export default PostContent;
  • getStaticProps の中で全ての記事を取得し、記事内の日付からソートを行い、記事のファイル名を配列に入れる。
  • その配列 slugs と呼び出された記事自身 slug とreturnするprops内に含める

リンクを生成するコンポーネントを作成

./components/PageLinks.jsx
import Link from "next/link";
import styled from "styled-components";
const NextPage = styled.div`
padding: 10px 0;
float: left;
`;
const PreviousPage = styled.div`
padding: 10px 0;
text-align: right;
`;
const BlogsPage = styled.div`
clear: both;
`;
const Path = "blog"
const PageLinks = (props) => {
const nextIndexOf = props.slugs.indexOf(props.slug) - 1;
const nextSlug = props.slugs[nextIndexOf];
const preIndexOf = props.slugs.indexOf(props.slug) + 1;
const preSlug = props.slugs[preIndexOf];
return (
<>
<div>
<NextPage>
{nextSlug && (
<Link href={`/${Path}/${nextSlug}`}>
<a>Next Post</a>
</Link>
)}
</NextPage>
<PreviousPage>
{preSlug && (
<Link href={`/${Path}/${preSlug}`}>
<a>Previous Post</a>
</Link>
)}
</PreviousPage>
</div>
<BlogsPage>
<Link href={`/${Path}/`}>
<a>Back to Blogs Page</a>
</Link>
</BlogsPage>
</>
);
};
export default PageLinks;

親コンポーネントから受け取るもの

  • slug : レンダリング対象の記事(markdownのファイル名)
  • slugs : 日付でソートされた全ての記事(markdownのファイル名)の配列

slug を基準に一つ前の記事を Next Post として、一つ後の記事を Previous Post としてリンクを返す

コンポーネントを呼び出す

[slug].js
import PageLinks from "../../components/PageLinks";
(snip)
const PostContent = ({ post }) => {
return (
<>
<Head>
<title>{post.title} | WOF Tech Blog</title>
</Head>
<article>
<ArticleHeader title={post.title} date={post.date} />
<div className={styles.body}>
<MDXRemote {...post.mdxSource} components={components} />
</div>
{/*コンポーネントの呼び出し*/}
<PageLinks slug={post.slug} slugs={post.slugs}/>
</article>
</>
);
};