🐡

【Next.js】APIフォルダで記事データを管理する

2023/03/07に公開

背景

前回の記事に引き続き、声優さんの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作成

まず、WORKSNEW WORKSのデータを作成します。

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)
}

一覧を表示する

次に、WORKSNEW 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