Next.js Tutorial -- 詳細部分の pages/posts/hoge.md からの自動生成ページを作る
[id].js を作る
前回の記事でリストページは完成したので、今回は詳細ページを作る
pages/ に
posts/[id].js を作る
この [id] のところに ファイル内部の getStaticPaths で渡された値が入る。
import Layout from '../../components/layout' export default function Post() { return <Layout>...</Layout> }
layout を import して
Layout に挟む中身をとりあえず書く
ここでは id を使ってそれで url を決定するので、 まずは markdown のファイルたちから id をとってくる関数を作る
lib/posts/getAllPostsIds/ を作る
前回作った posts.js の getSortedPostsData に並べて getAllPostsIds を作る
export function getAllPostsIds() { const fileNames = fs.readdirSync(postsDirectory); return fileNames.map(fileNames => { return { params: { id: fileName.replace( /\.md$/, '') } } }) }
posts/ から中身を読み取り fileNames という変数に入れる
fileNames を map して
params: { id: fileName を .md 引いたもの }
を関数の戻り値として返すようにする
[id]/getStaticPaths で url に動的に渡せるようにする
先ほどの getAllPostsIds で posts/ から中身を params の形で持ってこれるようになった
その params の形で整形された id たちを 個別の url として使うためには
getStaticPath を 自動生成の詳細ページの冒頭で使う必要があるらしい
import { getAllPostIds } from '../../lib/posts'
[id].js で id たちをとってくる関数を import
export async function getStaticPaths() { const paths = getAllPostIds() return { paths, fallback: false } }
getStaticPaths に求められた形で paths に渡し、fallback を false にする
これだけではアクセスできない。404 になってしまう
とりあえず getStaticProps にも渡す
Post/ の本文を持ってくる
getStaticProps に渡すデータを引き出す関数を作る
lib/posts.js に3つ目の関数を追加する
id をもとに post の data を get する
getPostData(id) である
export function getPostData(id) { const fullPath = path.join(postsDirectory, `${id}.md`); const fileContents = fs.readFileSync(fullPath, 'utf8'); const matterResult = matter(fileContents); return { id, ...matterResult.data } }
posts/ の読み取るディレクトリのパスを定義し、
そのパスから utf 8 でファイルの中身の内容物を読み取る
その内容物に matter をかけて ヘッダーのメタ情報と分離する。
ここまでは先に書いた allPostsData と同じ..ではなく、
map してきた fileName を処理するものから、引数に持ってきた id でパスをしゅとくするものに変わっている。
そこから引数の id と matterResult.data を
[id, ThatContentsData]
の形で返すようにする
[id].js で getStaticProps で post の data を書き出す
今作った関数実際に view の 詳細である pages/posts/[id] で使用する
import { getAllPostIds, getPostData } from '../../lib/posts'
getPostData として、引数は書かずに import してくる。
export async function getStaticProps({ params }) { const postData = getPostData(params.id) return { props: { postData } } }
上部で getStaticProps を作り getStaticProps に
引数の params の id から post の data を さっき作った getPostData で持ってきて
それを
props: { ThatPostDataOfId} の形で渡す
引数の params は おそらく getStaticPaths で受け取った paths の params から使えるようになっている。
??この時点でアクセスができるように... ならない。
Post の表示の部分を
export default function Post() { return <Layout>posts</Layout> }
これから
export default function Post({ postData }) { return ( <Layout> {postData.title} <br /> {postData.id} <br /> {postData.date} </Layout> ) }
postData に書き換える。
これでもアクセスできない
Attempted import error: 'getAllPostIds' is not exported from '../../lib/posts'.
複数形にしてた、コンソールにエラー出てた
return fileNames.map(fileName => {
fileName => のはずが fileNames => になっていた。
これでページが見れるようになった。