KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

Next.js Tutorial -- 詳細部分の pages/posts/hoge.md からの自動生成ページを作る

[id].js を作る

前回の記事でリストページは完成したので、今回は詳細ページを作る

nextjs.org

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 => になっていた。

f:id:kei_s_lifehack:20210126073455p:plain

これでページが見れるようになった。