🐡
【Next.js】APIフォルダで記事データを管理する
背景
前回の記事に引き続き、声優さんのHPのtracingをしています。
以下ページでは、<li>
などがベタがきされていたので、それをAPIフォルダとmap()
を使って簡単にしてみました。
WORKS
NEW WORKS
フォルダ構成
pages
pages
├── _app.tsx
├── _document.tsx
├── api // この記事で作成
│ ├── newWorks
│ │ └── index.tsx
│ └── works
│ └── index.tsx
├── index.tsx
├── new // NEW WORKSページ
│ └── index.tsx
├── profile
│ └── index.tsx
└── works // WORKSページ
└── index.tsx
components
components
├── ...(略)...
├── workList //今回作成
│ ├── list.module.scss
│ └── list.tsx
└── works
├── works.module.scss
└── works.tsx
API作成
pages/api/newWorks/index.tsx
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
// オブジェクトの型指定
interface WorkInfo {
text: string
href: string
}
type Data = {
pageTitle: string,
playingTitle: string,
planningTitle: string,
playingWorks: Array<WorkInfo>
planningWorks: Array<WorkInfo>
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const result: Data = {
pageTitle: 'NEW WORKS',
playingTitle: "放映中の作品",
playingWorks: [
{
text: "「パンドラとアクビ」役:ルイーズ 4/5〜ロードショー",
href: 'https://dora-bi.com'
},
...(略)...
],
planningTitle: "放映予定の作品",
planningWorks: [
...(略)...
],
}
res.status(200).json(result)
}
pages/api/works/index.tsx
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
// オブジェクトの型指定
interface WorkInfo {
text: string
}
type Data = {
pageTitle: string,
foreignTitle: string,
movieTitle: string,
foreignWorks: Array<WorkInfo>
movies: Array<WorkInfo>
actors: string[]
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const result: Data = {
pageTitle: 'Works',
foreignTitle: "吹き替え(海外ドラマ)",
foreignWorks: [
{
text: "「NCIS:ニューオーリンズ シーズン3〜」役:タミー・グレゴリオ(ヴァネッサ・フェルリト)",
},...(略)...,
],
movieTitle: "吹き替え(映画)",
actors: ["アン・ハサウェイ",...(略)...],
movies: [...(略)...],
}
res.status(200).json(result)
}
一覧を表示する
次に、WORKS、NEW WORKSのデータをpages
のファイルで表示します。
一覧の表示はmap()
で行いますが、いちいちmap()
を書いていくのは面倒なので、
コンポーネントでリストを指定するだけで表示されるようにしました。
WorkListコンポーネント
import Works from "../works/works";
import classes from "./list.module.scss";
type Contents = {
text: string
href?: string
}
type PropsType = {
lists: Contents[]
useComponents?: boolean // NEW WORKSのページでは、Worksコンポーネントを使う
}
export default function WorkList(props: PropsType) {
const lists = props.lists
if (props.useComponents) {
return (
<>
{lists.map((item, i: number) => (
<Works
key={i}
text={item.text}
href={item.href}
></Works>
))}
</>
)
} else {
return (
<ul className={classes.work__list}>
{lists.map((item, i: number) => (
<li
key={i}
>
<span className={classes.work__span}>●</span>
{item.text}
</li>
))}
</ul>
)
}
}
Worksコンポーネント
import classes from './works.module.scss'
import Link from "next/link";
type PropsType = {
text: string
href: string
}
export default function Works(props: PropsType) {
return (
<div className={classes.works}>
<section className={classes.works__section}>
<p className={classes.works__text}>
{props.text}
<br />
<Link
className={classes.works__link}
href={props.href}
target="_blank">
{props.href}
</Link>
</p>
</section>
</div>
)
}
結果
CSSは最小限しか指定していないので、元のHPと差分はありますが、
無事エラーなく表示されました!
Discussion