【React】PokemonAPIを使用してポケモンの情報を取得する

みなさんこんにちは。

小学2年生になる息子がいるのですが、

ポケモンが大好きです。

かつ、今後のICT教育を見据え、パソコンにはどんどん触れてほしいと思い、ポケモンアプリを開発しました。

ゲームボーイカラー風ポケモンアプリ

【参考:ゲームボーイカラー風ポケモンアプリを操作してみたい人】

開発したポケモンアプリの詳細については過去の記事で紹介させていただいております。

また、アプリの中でポケモンのBGMを流しているのですが、

そちらの再生方法、停止方法については以下で解説しております。

今回はPokemon APIを使用してポケモンのたかさ、おもさ、分類、説明文の取得方法について解説していきたいと思います。

この記事がおすすめな人

今回の記事は以下の人に特におすすめです。

  • React:初学者、初級者~中級者
  • アプリを開発したい人
  • 手順だけを知りたい人
  • コードだけを知りたい人

手順

Pokemon APIの存在と仕組みを理解する

まずは、Pokemon APIがどんなものがざっくりでいいので調べる必要があります。

【参考:【公式】Pokemon API についてはこちらで理解を深めましょう!】

変数と関数をコーディングする

新たにPokemonAPIでポケモンの「おもさ」「たかさ」「分類」「説明文」を取得します。

変数について

変数は以下の内容を用意します。

  const [pokemonhight  , setPokemonHight  ] = useState() // ポケモンの高さ
  const [pokemonweight , setPokemonWeight ] = useState() // ポケモンの重さ
  const [pokemontext   , setPokemonText   ] = useState() // ポケモンの説明文
  const [pokemongenus  , setPokemonGenus  ] = useState() // ポケモンの分類

「高さ」「重さ」の取得について

「高さ」「重さ」については以下のコードになります。

    // 高さを取得
    setPokemonHight((response.data.height / 10).toFixed(1))

    // 重さを取得
    setPokemonWeight((response.data.weight / 10).toFixed(1))

「高さ」「重さ」を取得する際は、メートル/キログラムで表現したいので、10で割ることと、小数点第一位まで表示するようにします。

「分類」の取得について

「分類」については、

ひらがな表記のほうがオリジナルに近い表現となるため”ja-Hrkt”とします。

漢字表記も交える場合は、”ja”とします。

なお、”レジェンドアルセウス”と”スカーレット/バイオレット”については、

画像と名前は存在していても、分類が存在しておりませんでした。

(今後のバージョンアップに期待したいですね!!!)

    // 分類、説明文を取得するための準備
    const speciesUrl = response.data.species.url
    const speciesResponse = await axios.get(speciesUrl)

    // 分類を取得
    const genera = speciesResponse.data.genera
    const genus = genera.find((v) => v.language.name == "ja-Hrkt")
    setPokemonGenus(genus.genus)

「説明文」の取得について

「説明文」についてはかなり癖があります。

バージョンごとに登場するポケモンが違ってくるので、分岐処理が必要になります。

なお、”レジェンドアルセウス”と”スカーレット/バイオレット”については、

画像と名前は存在していても、説明文が存在しておりませんでした。

「分類」同様ひらがな表記のほうがオリジナルに近い表現となるため”ja-Hrkt”とします。

漢字表記も交える場合は、”ja”とします。

コードは以下のようになります。

    // ポケモンの名前を取得
    const japaneseName = speciesResponse.data.names.find(name => name.language.name === "ja").name
    setPokemonName(japaneseName)

    // 説明文取得
    const flavorTextEntries = speciesResponse.data.flavor_text_entries
    console.log(flavorTextEntries)
    let flavorText = flavorTextEntries.filter(function(v) {
      return (v.language.name == "ja-Hrkt") && (v.version.name == "sword")
    })
    if (flavorText.length == 0) {
      // バージョンをYで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "y")
      })
    }
    if (flavorText.length == 0) {
      // バージョンをサンで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "sun")
      })
    }
    if (flavorText.length == 0) {
      // バージョンをウルトラサンで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "ultra-sun")
      })
    }
    let cleanedText = flavorText[0].flavor_text
    console.log(cleanedText)
    // 説明文が見つからないとき
    if (cleanedText.length < 0){
      console.log(cleanedText)
      cleanedText = "ポケモンのデータがありませんでした。"
    }
    setPokemonText(cleanedText)

コンポーネントを作成する

テキストボックスに任意の数字を入れて、

「ポケモンのおもさ」、「ポケモンのたかさ」、「ポケモンの分類」、「ポケモンの説明文」を

表示するコンポーネントを追加します。

前回の画面構成については、過去記事の内容をご参照ください。

コードは以下のようになります。
            {/* ポケモンのおもさ */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンのおもさ:{pokemonweight} kg</Typography>
            </Grid>
            {/* ポケモンのたかさ */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンのたかさ:{pokemonhight} m</Typography>
            </Grid>
            {/* ポケモンの分類 */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンの分類:{pokemongenus} </Typography>
            </Grid>
            {/* ポケモンの説明文 */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンの説明文:{pokemontext} </Typography>
            </Grid>        

コード全体の記述(完成形)

過去のブログでも紹介させていただいた記述に今回の記述内容を加えています。

コード全体では以下の通りとなります。

import   React      ,
       { useState   ,} from "react"
import { TextField  , 
         Typography ,
         Box        ,
         Grid       ,
         Container  ,
         Button     ,} from "@mui/material"
import   axios         from 'axios'

function PokemonGetImg() {
  const [value         , setValue         ] = useState() // 答えのテキストボックスに入力している値
  const [pokemonname   , setPokemonName   ] = useState() // ポケモンの名前
  const [pokemonImage  , setPokemonImage  ] = useState() // ポケモン画像表示
  const [pokemonhight  , setPokemonHight  ] = useState() // ポケモンの高さ
  const [pokemonweight , setPokemonWeight ] = useState() // ポケモンの重さ
  const [pokemontext   , setPokemonText   ] = useState() // ポケモンの説明文
  const [pokemongenus  , setPokemonGenus  ] = useState() // ポケモンの分類


  // テキストボックスの内容
  const handleChange = (event) => {
    // 入力された値が数字でない場合は削除します
    const inputValue = event.target.value.replace(/[^0-9]/g, '')
    setValue(inputValue)
    console.log(value)
  }

  // ポケモンAPIを呼び出す
  const fetchPokemonImages = async () => {
    // ポケモンAPIを呼び出す
    const response = await axios.get("https://pokeapi.co/api/v2/pokemon/" + value)
    // ポケモンの画像を取得
    setPokemonImage(response.data.sprites.front_default)

    // 高さを取得
    setPokemonHight((response.data.height / 10).toFixed(1))

    // 重さを取得
    setPokemonWeight((response.data.weight / 10).toFixed(1))

    // 分類、説明文を取得するための準備
    const speciesUrl = response.data.species.url
    const speciesResponse = await axios.get(speciesUrl)

    // 分類を取得
    const genera = speciesResponse.data.genera
    const genus = genera.find((v) => v.language.name == "ja-Hrkt")
    setPokemonGenus(genus.genus)

    // ポケモンの名前を取得
    const japaneseName = speciesResponse.data.names.find(name => name.language.name === "ja").name
    setPokemonName(japaneseName)

    // 説明文取得
    const flavorTextEntries = speciesResponse.data.flavor_text_entries
    console.log(flavorTextEntries)
    let flavorText = flavorTextEntries.filter(function(v) {
      return (v.language.name == "ja-Hrkt") && (v.version.name == "sword")
    })
    if (flavorText.length == 0) {
      // バージョンをYで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "y")
      })
    }
    if (flavorText.length == 0) {
      // バージョンをサンで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "sun")
      })
    }
    if (flavorText.length == 0) {
      // バージョンをウルトラサンで取得し直す.
      flavorText = flavorTextEntries.filter(function(v) {
        return (v.language.name == "ja-Hrkt") && (v.version.name == "ultra-sun")
      })
    }
    let cleanedText = flavorText[0].flavor_text
    console.log(cleanedText)
    // 説明文が見つからないとき
    if (cleanedText.length < 0){
      console.log(cleanedText)
      cleanedText = "ポケモンのデータがありませんでした。"
    }
    setPokemonText(cleanedText)
  }

  return (
    <Container maxWidth="sm">
      <Box sx={{ flexGrow: 1,
                   bgcolor: '#f5f5f5' }}>
          {/* テキスト表示領域 */}
          <Grid container spacing={2}>
            <Grid item xs={12} align="center">
              <Typography>
                ポケモン画像を取得
              </Typography>
            </Grid>
            <Grid item xs={12} align="center">
              <Typography>
                数字を入力
              </Typography>
            </Grid>
            <Grid item xs={6} align="right">
              <TextField 
                value={value}
                onChange={handleChange}>
              </TextField>
            </Grid>
            <Grid item xs={6} align="left">
              <Button variant='contained'
               onClick={fetchPokemonImages}>
                ポケモンを取得
              </Button>
            </Grid>
            {/* ポケモン表示 */}
            <Grid item xs={12} align="center">
              <img
                src    = {pokemonImage}
                width  = "150px"
                height = "150px"/>
            </Grid>
            {/* ポケモンの名前 */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンの名前:{pokemonname} </Typography>
            </Grid>
            {/* ポケモンのおもさ */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンのおもさ:{pokemonweight} kg</Typography>
            </Grid>
            {/* ポケモンのたかさ */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンのたかさ:{pokemonhight} m</Typography>
            </Grid>
            {/* ポケモンの分類 */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンの分類:{pokemongenus} </Typography>
            </Grid>
            {/* ポケモンの説明文 */}
            <Grid item xs={12} align="center">
              <Typography>
                ポケモンの説明文:{pokemontext} </Typography>
            </Grid>            
          </Grid>
      </Box>
    </Container>
  )
}

export default PokemonGetImg

完成形の画面は以下のようになります。

検証

テキスト内に150を入力して「ポケモン取得」ボタンをクリックします。

ミュウツーの情報がすべて取得できました。

最後に

いかがでしたでしょうか。

Pokemon APIは活用方法によってはかなり細かい情報を取得できます。

レスポンスはもう少し複雑になりますが、バージョンごとの取得方法なども、

コードの書き方によっては指定できるので勉強する価値はじゅうぶんあるかと思います。

まずは基本をしっかりと理解していただければともいます。

開発依頼について

ココナラでWebアプリ開発サービスを出品しております。

自分で開発をしようと思ったけど、依頼したり、何か聞きたいことがあったりしたら

いつでもお気軽にご相談ください。

また、内容についてご不明点があればメッセージをいただけると幸いです。

スモールスケールのWebアプリ開発します 先ずはスモールスケールのWebアプリから始めませんか?

Excelにてブラウザ操作自動化ツールを作成します その作業、webスクレイピングを使って自動化しましょう!

業務効率化(RPA)ツールを開発します Excelの”便利”を使って、業務効率化をご提供します!

ご興味がある方はこちら!!