【React】外部API(JSON)を取得して表示する方法

React

Reactで外部API(JSON)を取得して表示する方法を紹介します。
今回は、ポケモンAPIで実際に取得して表示します。

Reactで外部API(JSON)を取得して表示する方法

ファイル構成

src
∟App.js
∟index.js
∟components
∟Card
∟Card.js
∟utils
get.js
App.jsでループして外部API(JSON)を取得した分だけCardを作成する構成とします。

index.js

import React from 'react';
  import ReactDOM from 'react-dom/client';
  import './index.css';
  import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
  <App />
  </React.StrictMode>
  );

上でAppを読み込みます。
index.jsは特にいじるところはありません。

App.js

import { useEffect, useState } from "react";
  import "./App.css";
  import Card from "./components/Card/Card";
  import { getPokemon } from "./utils/get";

  function App() {
    // pokeAPI
    const initialURL = "https://pokeapi.co/api/v2/pokemon"; //endpoint
    const [loading, setLoading] = useState(true); //最初にloading出したいのでtrue
    const [pokemonData, setPokemonData] = useState([]);


    useEffect(() => {
      const fetchPokemonData = async () => {
        // すべてのポケモンデータを取得
        let res = await getPokemon(initialURL);
        // 詳細データを取得
        loadPokemon(res.results);
        setLoading(false);
      };
      fetchPokemonData();
    }, []);

    const loadPokemon = async (data) => {
      let _pokemonData = await Promise.all(
        // Promise.all(配列)、全部とってくるまで待つ
        data.map((pokemon) => {
          let pokemonRecord = getPokemon(pokemon.url);
          return pokemonRecord;
        })
      );
      setPokemonData(_pokemonData);
    };
    // console.log(pokemonData); //もしコンソールの結果がPromise {<pending>}というものなら、async-awaitつけ忘れ

    return (
      <>
        <Navbar />
        <div className="App">
          {loading ? (
            <p className="loader">ロード中。。。</p>
          ) : (
            <div>
              {pokemonData.map((pokemon, i) => {
                return <Card key={i} pokemon={pokemon} />;
              })}
            </div>
          )}
        </div>
      </>
    );
  }

  export default App;

ポケモンのAPIについて、https://pokeapi.co/が提供サイトです。
こちらから、JSONが返されるurlを探して、エンドポイントを設定します。
useEffectでは、最初だけ発火してほしいので、空の配列を第二引数に指定します。
非同期でデータを取得してくるので、async-awaitを使います。
async-awaitを使うことで、データの取得が完了した場合に、それ以降の処理が実行されます。
loadPokemon関数で使用しているPromise.all()メソッドを使うことで、非同期処理を並列で処理することができるようになります。全部とってくるまで待つという非同期の処理です。詳しくは、次の記事を参照してみてください。

loadPokemon関数では、新しいオブジェクトに取得したデータを格納して、それを更新用関数にセットすることで状態が変化します。

JSX部分では、Cardコンポーネントにpokemonのデータをpropsとして渡します。

utils/get

export const getPokemon = (url) => {
  return new Promise((resolve, reject) => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => resolve(data));
  });
};

urlエンドポイントを引数にとり、Promiseを使って、処理します。
resは、jsonデータが格納されているresponseオブジェクトです。
jsonデータをJavaScriptオブジェクトにするためには、json()メソッドを使います。

components/Card/Card.js

import React from "react";
  import "./Card.css";

  const Card = ({ pokemon }) => {
    return (
      <div className="card">
        <div>
          <img src={pokemon.sprites.front_default} alt={pokemon.name} />
          <h3>{pokemon.name}</h3>
          <div>
            <ul>
              <li>
                タイプ:
                {pokemon.types.map(type => {
                  return (
                    <div key={type.type.name}>
                      <span className="typeName">{type.type.name}</span>
                    </div>
                  )
                })}
              </li>
              <li className="title">能力: {pokemon.abilities[0].ability.name}</li>
              <li className="title">重さ: {pokemon.weight}</li>
              <li className="title">高さ: {pokemon.height}</li>
            </ul>
          </div>
        </div>
      </div>
    );
  };

  export default Card;

App.jsから渡されたpropsを分割代入して、pokemonとして受け取ります。
あとは、オブジェクトを確認して、それぞれ必要なプロパティを順次設定していくだけです。

React

Posted by devsakaso