🦻
Next.jsのサイトにmicroCMSをAPI接続する
今回はこのようなサイト内のニュース欄をmicroCMSを用いて作ります。
デプロイはAWS amplifyでする前提です。
microCMSの設定
(1)プロジェクトを作る
個人開発レベルではHobbyで事足りるかと(検証中)。
(2)APIを作成
リスト形式を選択
(3)投稿したい項目を定義
APIで取得したデータをmapで出す
(1)API keyを.envに書き込む
.env.production
NEXT_PUBLIC_API_KEY=your key
keyはこちら
(2)nextがexport出来るようにする
next.config.js
module.exports = {
env: {
X_API_KEY: process.env.X_API_KEY,
},
}
(3)pages/index
componentに書き込んでも、なぜかうまく動作しないので、直接pagesに書き込むことをお勧めします。
pages/index.tsx
import styles from '../styles/Home.module.scss'
import Link from 'next/link'
import React from 'react'
import Moment from 'react-moment'
import Icon from '../components/bases/IconCompo'
export const getStaticProps = async () => {
const key = {
headers: { 'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY },
}
const newsData = await fetch('apiURL', key)
.then((res) => res.json())
.catch(() => null)
return {
props: {
news: newsData.contents,
},
}
}
const Home = ({ news }) => {
return (
<div className={styles.news}>
<p className={styles.title}>ニュース</p>
<div className={styles.newsContainer}>
{news.slice(0, 4).map((news) => (
<Link href={`news/${news.id}`} key={news.id}>
<div className={styles.item}>
<tr>
<td className={styles.date}>
<Moment format="YYYY/MM/DD" style={{ marginRight: 30, color: '#a1a1a1;' }}>
{news.date}
</Moment>
</td>
<td className={styles.body}>{news.title}</td>
</tr>
</div>
</Link>
))}
</div>
<button className={styles.moreContainer}>
<span>
もっと見る
<Icon type="arrowRight" />
</span>
</button>
</div>
)
}
export default Home
・apiURLはこのページから取得します
・Momentは、別記事で紹介してます。
・.slice(0,4)は、直近の1番目から4番目までだけを表示します。
(4)CSS
.news {
text-align: center;
padding-top: 2%;
.title {
font-size: 30px;
font-weight: bold;
}
.newsContainer {
width: 50%;
margin: 0 auto;
border-top: solid 1px #e8e8e8;
.item {
width: 100%;
border-bottom: solid 1px #e8e8e8;
tr {
td {
cursor: pointer;
padding: 23px;
font-weight: bold;
text-align: left;
}
}
}
}
.moreContainer {
margin: 0 auto;
padding: 20px 0;
span {
display: flex;
justify-content: center;
align-items: center;
font-family: 'ten mincho text';
font-size: 15px;
font-weight: bold;
color: #606060;
}
}
これで外観は完成したかと思います。
(4)詳細を表示するページを作る
ニュースのタイトルをクリックしたときに、その詳細を表示させるページを作ります。
pages/newsを作成
pages/news/index.tsx
import styles from './id.module.scss'
import Moment from 'react-moment'
export const getStaticPaths = async () => {
const key = {
headers: { 'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY },
}
const data = await fetch('https://examplerenren.microcms.io/api/v1/news', key)
.then((res) => res.json())
.catch((err) => console.warn(err))
const paths = data.contents.map((content) => `/news/${content.id}`)
return { paths, fallback: false }
}
export const getStaticProps = async (context) => {
const id = context.params.id
const key = {
headers: { 'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY },
}
const data = await fetch('https://examplerenren.microcms.io/api/v1/news/' + id, key)
.then((res) => res.json())
.catch((err) => console.warn(err))
return {
props: {
news: data,
},
}
}
const NewsId = ({ news }) => {
return (
<div>
<div className={styles.contents}>
<h1 className={styles.title}>{news.title}</h1>
<Moment format="YYYY/MM/DD" className={styles.date}>
{news.publishedAt}
</Moment>
<div className={styles.imgContainer}>
<img src={news.thumbnail.url} className={styles.thumbnail}></img>
</div>
<div
className={styles.body}
dangerouslySetInnerHTML={{
__html: `${news.body}`,
}}
/>
</div>
</div>
)
}
export default NewsId
これで表示できると思います。
getStaticPropsのところのapiのURLの最後に/を追加するのを忘れないでください。
1日ハマりました。
Discussion