ハリーポッターAPIとNext.jsを使って図鑑を作る

4/27(土)にXで募集されていたNext.jsの勉強会に参加してきました！
今回は勉強会で学んだ内容を簡潔にアウトプットします。

詳細は下記の記事を参照してください！
てるし〜さんという方が講師を務めてくださいました。

https://zenn.dev/terusi/articles/8a7f60db8b700b

## 概要
ハリーポッターのキャラクターの名前や画像が格納された、
ハリーポッターAPIというものがネットで公開されています。

今回はそのAPIを叩くことで、キャラクターの名前や画像を取得して
簡易的なハリーポッター図鑑を作成していきます。

https://hp-api.onrender.com/

## APIを叩く
Next.jsについては、僕もまだ学習中の段階なので間違いや説明不足の
部分があったらごめんなさい🙇‍♂️

まずは、ハリーポッターAPIのurlを.envファイルに書きます。

```.env
NEXT_PUBLIC_URL1="https://potterapi-fedeperin.vercel.app/es/characters"
```

こうすることで、NEXT_PUBLIC_URL1にfetchを使ってアクセスしキャラクターの
全体情報を取得することができます。

次に実際にAPIを叩いていきます。

```characters.ts
import { HPType } from "../types"

export const characters = async () => {
    const res = await fetch(process.env.NEXT_PUBLIC_URL1 as string)
    const data = (await res.json()) as HPType[]

    return data
}
```

as stringというものがありますが、こうすることによってstring型として扱うという
型指定ができます。また、as HPType[]とすることで自分が作ったHPTypeの型に合わせて
取得することができます。

HPTypeについては別のファイルで指定します。

```types.ts
export type HPType = {
    fullName: string
    nickname: string
    hogwartsHouse: string
    interpretedBy: string
    children: string[]
    image: string
    birthdate: string
    index: number
}
```

これによって、キャラクターの名前や画像を
props.data.fullNameやprops.data.imageとして取得できます。

データを取得するためのReact Hooksライブラリとして、
SWRを使用します。

```useCharacters.ts
import useSWR from "swr"
import { characters } from "../fetcher"

export const useCharacters = () => {
  const { data, isLoading } = useSWR(process.env.NEXT_PUBLIC_URL1, characters)

  return {
    data, 
    isLoading
  }
}
```

以下、説明を省きますがコードを掲載します。
コンポーネントを作成して、それに対してpropsを設定してデータの受け渡しを
しているはずです。。。(理解不足ですみません🙇‍♂️)

```RSC.tsx
import { CharactersTemplate } from "@/components/layout/charactersTemplate"
import { characters } from "@/model/fetcher"

export const RSC = async () => {
    //データを取得！
    const data = await characters()

    return (
        <CharactersTemplate
            data={data}
            title="RSCで作るハリーポッター図鑑"
            path="/serverSide/"
        />
    )
}
```

```page.tsx
import { characters } from "@/model/fetcher"
import { RSCCharacter } from "@/view/RSC/RSCCharacterDetail"

interface props {
    id: string
}

export const generateStaticParams = async () => {
    //ここの部分を書きましょう
    const data = await characters()

    const paths = data.map((item) => {
        id: item.fullName
    })

    return paths
}

//ここの部分もちょろっと
const ClientCharacter = ({ params }: { params: props }) => {
    return <RSCCharacter id={params.id} />
}

export default ClientCharacter
```

```CharactersTemplate.tsx
import { HPType } from "@/model/fetcher"
import styles from "./style.css"
import { BackButton } from "@/components/ui/backButton"
import Image from "next/image"
import Link from "next/link"

interface props {
    data: HPType[]
    title: string
    path: string
}

export const CharactersTemplate = (props: props) => {
    return (
        <main className={styles.container}>
            <header className={styles.header}>
                <div className={styles.backButton}>
                    <BackButton />
                </div>
                <div className={styles.titleTextBox}>
                    <h1>{props.title}</h1>
                </div>
            </header>

            <section>
                <div className={styles.itemImage}>
                    {/* ここにデータを集めたものを書く 画像サイズは幅175、高さ250 */}
                    {props.data.map((item, index) => (
                        <div key={index}>
                            <Image
                                src={item.image}
                                width={175}
                                height={250}
                                alt=""
                            />
                            <div>
                                <Link href={`${props.path}${item.fullName}`}>
                                    <button className={styles.button}>
                                        detail
                                    </button>
                                </Link>
                            </div>
                        </div>
                    ))}
                </div>
            </section>
        </main>
    )
}
```

## まとめ
記事の中でディレクトリ構造について触れることができなかったのですが、
今回の勉強会ではてるし〜さんから、「ディレクトリが実はとても大切である！」という
話しを受けました。ディレクトリ構造を意識することで、自分がいまどの部分を
いじっているのかといったことや、バグが起きたときにファイルの場所の特定を
しやすくなるというメリットがあります。

これからの開発ではディレクトリの構造についてより意識して開発していきたいです！
最後になりますが、勉強会を開催してくれたみぃさん、てるし〜さん、当日お会いした
みなさま方ありがとうございました〜！おかげさまで楽しく勉強できました😊