PokéAPIを用いて簡単なポケモン図鑑を作ってみた

## はじめに
こんにちは、今回はPokéAPIを使用して簡単なポケモン図鑑を作成する方法を紹介します。最近、ポケモン関連のアプリやゲームが人気を集めている影響で、自分でもポケモン図鑑を作ってみることにしました。また、UdemyでPokéAPIの使い方を学んだ経験を活かし、その知識をまとめた記事です。

[PokéAPI公式サイト](https://pokeapi.co/)

## 環境構築

### 1. プロジェクトの作成
Reactのプロジェクトを作成するために、npm create vite@latest を使って新しいReactアプリを作成しました。

```bash
npm create vite@latest
```
### 2. プロジェクトの構造

```bash
pokemon-app/
├── node_modules/          # 依存関係がインストールされるディレクトリ
├── public/                # publicフォルダ、HTMLや画像などが配置される
│   ├── favicon.png
│   └── ...
├── src/                   # アプリケーションのソースコード
│   ├── App.tsx            # メインのReactコンポーネント
│   ├── index.tsx          # アプリケーションのエントリーポイント
│   └── ...
├── index.html             # メインのHTMLファイル
├── package.json           # プロジェクトの設定ファイル
├── ts.config.json         # TypeScriptの設定ファイル、型チェックやコンパイルオプション
├── vite.config.ts         # Viteの設定ファイル、開発サーバーやビルド設定をカスタマイズ
└── ...
```

## 実装したこと
具体的には以下のことを実装しました。
### 1. ポケモンデータの取得
ポケモンのデータは、PokéAPIから取得しています。このAPIを使って、fetch関数を使い、ポケモン一覧のデータを取得しています。
具体的には、https://pokeapi.co/api/v2/pokemon というURLを指定し、ポケモンの基本情報を取得します。
レスポンスには、ポケモンの名前やURLが含まれており、各ポケモンの詳細情報を取得するために、このURLを使ってさらにfetchリクエストを行います。

### 2. ページネーション機能
ページネーション機能では、PokéAPIから取得したデータ内にある`next`や`previous`プロパティを使って次ページ・前ページへの遷移を実装しています。例えば、以下のようなURLになります。

- `next`: "https://pokeapi.co/api/v2/pokemon?offset=20&limit=20"
- `previous`: null

`offset`はデータ取得開始位置、`limit`は一度に取得する件数を指定しています。この情報を使って次ページへ進むためには、新しいURLで再度リクエストするだけです。

### 3. ポケモンデータの表示
取得した情報にあるデータを一部表示して簡単なポケモン図鑑をつくっていきます。
今回使ったデータはこちらです。

| データ | 説明 |
|:-:|:-:|
|sprites.front_default|ポケモンの正面から見た公式画像URL   |
|name|   ポケモンの名前|
|types|   ポケモンのタイプ情報|
|weight|   ポケモンの重さ（デカグラム単位）|
|height|   ポケモンの高さ（デシメートル単位）|
|ability|   ポケモンのとくせい|

実際にこのような感じで表示できました。

![スクリーンショット 2024-11-12 12.00.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795604/c16190ae-d10a-be3a-eccc-9bc3437fda9c.png)

しかし、ポケモン名や特性が英語で表示されることが気になったため、日本語対応も追加実装しました。

そのためにこちらのデータが必要でした。

| データ | 説明 |
|:-:|:-:|
|  species |  ポケモンの種族情報 |

例えば、以下は「フシギダネ」の種族情報です。
```
species: 
name: "bulbasaur"
url:  "https://pokeapi.co/api/v2/pokemon-species/1/" 
```

このURLから日本語名や日本語タイプ名などが取得できます。以下はその実装例です。

```/src/utils/pokemon.ts
//日本語のポケモン名を取得
export const getPokemonJapaneseName = async (url: string): Promise<string> => {
  const response = await fetch(url);
  const data = await response.json();
  const japaneseName = data.names.find(
    (name: { language: { name: string } }) => name.language.name === "ja"
  )?.name;
  return japaneseName || "名前なし";
};

//日本語のタイプを取得
export const getPokemonTypes = async (types: TypeData[]): Promise<string[]> => {
  const typeUrls = types.map((type) => type.type.url);
  const typeNames = await Promise.all(
    typeUrls.map(async (url) => {
      const response = await fetch(url);
      const data: { names: NameData[] } = await response.json();
      const japaneseName = data.names.find(
        (name) => name.language.name === "ja"
      )?.name;
      return japaneseName || "タイプなし";
    })
  );
  return typeNames;
};

//日本語のとくせいを取得
export const getPokemonAbilityJapaneseName = async (url: string) => {
  const response = await fetch(url);
  const data: { names: NameData[] } = await response.json();
  const japaneseName = data.names.find(
    (name) => name.language.name === "ja"
  )?.name;
  return japaneseName || "とくせいなし";
};
```

``` src/App.tsx
  const loadPokemon = async (data: { url: string }[]) => {
    let _pokemonData = await Promise.all(
      data.map(async (pokemon) => {
        let pokemonRecord = await getPokemon(pokemon.url);
        //ポケモンの種族の日本語名を取得し、japaneseName変数に格納
        const japaneseName = await getPokemonJapaneseName(
          pokemonRecord.species.url
        );
        //ポケモンのタイプの日本語名を取得し、pokemonTypes変数に格納
        const pokemonTypes = await getPokemonTypes(pokemonRecord.types);
        const abilityPromises = pokemonRecord.abilities.map(async (ability) => {
          return await getPokemonAbilityJapaneseName(ability.ability.url);
        });
        //ポケモンの特性の日本語名を取得し、japaneseAbilities変数に格納
        const japaneseAbilities = await Promise.all(abilityPromises);

        return {
          ...pokemonRecord,
          japaneseName,
          typesInJapanese: pokemonTypes,
          abilitiesInJapanese: japaneseAbilities,
        } as PokemonData;
      })
    );
    setPokemonData(_pokemonData);
  };
  ```

この部分で日本語名や日本語タイプ名、日本語特性名が抽出されます。結果として、このように表示できました。※一部修正

  ![スクリーンショット 2024-11-12 19.40.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795604/d622e10f-0898-406d-13e3-96daa81b5aa9.png)

他にも技や登場シリーズなどもあるので、自分好みに拡張可能です。
## さいごに

今回作成したポケモン図鑑アプリはGitHub上で公開しています。ソースコードも確認できますので、ご興味ある方はぜひチェックしてみてください。また、このアプリはデプロイ済みなので実際に動作も確認できます。

 https://github.com/Sho0226/pokemon-app