Next.jsで前の記事・次の記事へのリンクを作る
Next.jsで投稿した記事の下部に前の記事・次の記事へのリンクを作成する際のメモ。
仕上がりのイメージ
日付でソートされた全記事の配列を作成
[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.jsximport 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].jsimport 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></>);};