【Next.js】【contentful】動的なルーティングを利用した詳細ページの作成
こんにちは、本日はcontentfulのエントリーの内容を詳細ページに追加していこうと思います。
なお、エントリーは一記事単位の呼び方です。
(下記図参照)
結果
以下が全体図です。
//pages/posts/[slug].js import { createClient } from "contentful"; import Image from "next/image"; import { documentToReactComponents } from "@contentful/rich-text-react-renderer" const client = createClient({ space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID, accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN, }); export const getStaticPaths = async () => { //article 全件取得 const res = await client.getEntries({ content_type: "article" }) //全件のパラメーターだけを配列形式で取得 //[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } } ] const paths = res.items.map(item => { return { params: { slug: item.fields.slug } } }) return { paths, fallback: false } } export async function getStaticProps({ params }) { const { items } = await client.getEntries({ content_type: "article", "fields.slug": params.slug }) return{ props: { article: items[0] } } } export default function ArticleDetails({ article }) { const { thumbnail, Title, detail} = article.fields return ( <div> //省略 </div> ); };
Dynamic Routes(動的なルーティング)
Next.jsでは設定したファイル名が自動的にスラッグになります。
また[params].js
などのようにしてファイル名に角括弧(ブラケット)を使うことで
動的なルーティングを作成できます。
つまり
* pages/post/create.js
は /post/create
にマッチします。
* pages/post/[sulg].js
は /post/1
や /post/abc
にマッチします。
contentfulのインポート
contentfulをインポートします。
import { createClient } from "contentful";
spaceIDとaccessTokenを入力し
contentfulにアクセスするapiを取得します。
const client = createClient({ space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID, accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN, });
それぞれのエントリーのslug名を全件取得
content_type
がarticle
のエントリー(記事)をjson形式で取得、
それぞれのslugと言う項目だけを返すようにします。
下記のような形が返却されます。
[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } ,....} ]
//article 全件取得 const res = await client.getEntries({ content_type: "article" }) //全件のパラメーターだけを配列形式で取得 //[ { params: { slug: 'test2' } }, { params: { slug: 'test1' } } ] const paths = res.items.map(item => { return { params: { slug: item.fields.slug } } }) return { paths, fallback: false }
ちなみにslugのcontentful側での設定は
content model から手動で設定しているものになります。
urlに該当するエントリーを取得
現在のurlに該当するエントリーをgetEntries関数で取得し
コンポーネント側にpropsを渡します。
export async function getStaticProps({ params }) { const { items } = await client.getEntries({ content_type: "article", "fields.slug": params.slug }) return{ props: { article: items[0] } } } export default function ArticleDetails({ article }) { console.log(article) return ( <div> //省略 </div> ); };
以上です!、、思ったより手こずりました。
ただ、youtubeで英語でガッツリ解説してくれている動画を見つけて
そこから意外とスムーズにいきました。
おしまい