原文: How To Use Axios With React: The Definitive Guide (2021)

このガイドでは、React フックを盛り込んだ多くの実例を使用することによって、React で Axios.js を正しく使用する方法がわかります。

まず、なぜデータの取り込みライブラリとして Axios を使用すべきなのかについてお伝えし、React で Axios を設定する方法と、主要な 4 つのタイプの HTTP リクエストを Axios で送信する方法について見ていきます。

その後、再利用性を良くするために Axios インスタンスを作成し、わかりやすくするために async-await を使用する方法や、カスタムフックとして Axios を使用する方法など、より高度な機能について触れます。

さっそくはじめましょう!

プログラムの写しが必要ですか?‬ 📄

PDF 形式のチートシートをダウンロードするにはこちらをクリックしてください (5 秒で終わります)。

このチートシートは、この記事の重要な情報をすべて含んでいる、便利な PDF ガイドです。

目次

Axios とは?

Axios とは、特定のエンドポイントへのリクエストを送信できるようにする、HTTP クライアントライブラリです:

Screen-Shot-2021-07-12-at-1.14.41-PM-2

たとえば、外部 API や独自のバックエンド Node.js サーバーを、Axios で実装できます。

リクエストを送信することで、API に、そのリクエストに応じた処理の実行を要求します。

たとえば、GET リクエストを送信した場合は、アプリケーションの中で表示するデータを返信するように要求します。

なぜ React の中で Axios を用いるのか?

HTTP リクエストの送信に使用できる、さまざまなライブラリが数多く存在しているにもかかわらず、なぜ Axios を選択するのでしょうか?

HTTP リクエストを送信するクライアントとして、 Axios を使用すべき 5 つの理由を、以下に挙げます:

  1. Axios は、初期設定で JSON 形式のデータをうまく扱うことができます。Fetch API などの別のものと違い、多くの場合はヘッダーを設定する必要がありません。また、リクエストボディを JSON 文字列へ変換するといった、面倒な作業を行う必要がありません。
  2. Axios には、主な HTTP メソッドと一致する名前の関数が用意されています。GET リクエストを送信する時は、.get() メソッドを使用します。
  3. Axios は、より少ないコードでより多くのことを行います。Fetch API と違い、一度だけ .then() コールバックを用いれば、リクエストした JSON データにアクセスできます。
  4. Axios にはより良いエラー処理機能があります。ステータスコードをチェックして、エラーを自分で返さなければならない Fetch API と違い、Axios は 400 番台と 500 番台のエラーレスポンスステータスコードを返します。
  5. Axios は、クライアント側でもサーバー側でも使用できます。Node.js でアプリケーションのコードを記述している場合は、ブラウザーとは別の環境の中でも Axios を使用できることに注意してください。

React で Axios を設定する方法

React で Axios を使用する手順はとても簡単です。以下の 3 つのことが必要です:

  1. React のプロジェクトを作成してあること
  2. npm または yarn で Axios をインストールすること
  3. リクエストを送信するための API エンドポイント

新しい React アプリケーションを最も早く作成する方法は、react.new を訪れることです。

すでに React のプロジェクトがある場合は、Axios を npm (または他のパッケージマネージャー) でインストールする必要があるだけです:

npm install axios

また、このガイドでは JSON Placeholder API を使って、投稿 (post) データを取得し、変更します。

リクエストを送信できる全てのルートについて、それぞれにふさわしい HTTP メソッドと一緒に記載したものの一覧がこちらです:

Screen-Shot-2021-07-10-at-12.21.28-PM-2

Axios と API のエンドポイントを使用して行う操作 (投稿の取得、作成、更新、削除) の手短な例がこちらです:

axios-react-2

GET リクエストを送信する方法

データを取得したり検索するには、GET リクエストを送信します。

最初に、個々の投稿に対してリクエストを送信してみましょう。エンドポイントを見てみると、 /posts/1 エンドポイントから最初の投稿を取得できます:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts/1";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(baseURL).then((response) => {
      setPost(response.data);
    });
  }, []);

  if (!post) return null;

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

useEffect フックを使って、コンポーネントがマウントされた時点でこのリクエストを送信します。これには Axios をインポートし、.get() メソッドを用いて GET リクエストをエンドポイントへ送信し、.then() コールバックを用いてすべてのレスポンスデータを取得することが伴います。

レスポンスはオブジェクトとして返されます。データ (この場合、 idtitlebody プロパティーを伴う投稿データ) は post と呼ばれるステートに格納され、コンポーネントの中で表示されます。

レスポンスの中の .data プロパティーから、常にリクエストされたデータを見つけることができるということに注意してください。

POST リクエストを送信する方法

新しいデータを作成するには、POST リクエストを送信します。

JSON Placeholder API の仕様に従い、POST リクエストを /posts エンドポイントに送信する必要があります。以下のコードを見てみると、投稿データを作成するボタンがあるのを確認できます:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function createPost() {
    axios
      .post(baseURL, {
        title: "Hello World!",
        body: "This is a new post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={createPost}>Create Post</button>
    </div>
  );
}

ボタンをクリックすると、createPost 関数を呼び出します。

Axios で POST リクエストを送信するには、.post() メソッドを使用します。作成しようとしている新しい投稿データを、オブジェクトのプロパティーとして記述し、第二引数として渡します。

もう一度 .then() コールバックを使ってレスポンスデータを取得し、最初に取得した投稿を、リクエストした新しい投稿 に置き換えます。

‌‌これは .get() メソッドとよく似ていますが、作成しようとしている新しいリソースが、API エンドポイントの後ろに第二引数として渡されています。

PUT リクエストを送信する方法

特定のリソースを更新するには、PUT リクエストを送信します。

以下の例では、最初の投稿を更新します。

そのためにもう一度ボタンを作成しましょう。ただし今回は、投稿を更新するための関数を、ボタンで呼び出します:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function updatePost() {
    axios
      .put(`${baseURL}/1`, {
        title: "Hello World!",
        body: "This is an updated post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={updatePost}>Update Post</button>
    </div>
  );
}

上のコードの中では、Axois の PUT メソッドを使用します。POST メソッドの場合と同じように、更新しようとしているリソースをオブジェクトのプロパティーとして記述し、第二引数として渡しています。

ここでまた .then() コールバックを用いて、返ってきたデータで JSX を更新します。

DELETE リクエストを送信する方法

最後に、リソースを削除するために、DELETE メソッドを使用します。

その例として、最初の投稿を削除してみましょう。

このリクエストを送信する時に、第二引数には何も必要ないことに注意してください:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    axios
      .delete(`${baseURL}/1`)
      .then(() => {
        alert("Post deleted!");
        setPost(null)
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

ほとんどの場合、.delete() メソッドから返ってきたデータは必要ありません。

ただし上のコードの中では、リクエストが正常に resolve (成功) したことを確かめるために、.then() コールバックがさらに用いられています。

上のコードの中で、投稿が削除された後に、ユーザーはうまく削除されたことを通知されます。それから、ステートの post の値が、初期値である null に設定されます。

また、一度投稿が削除されると、「No post」というテキストがアラートメッセージの後にすぐに表示されます。

Axios でエラーを扱う方法

Axios でエラーを扱うとはどういうことについて言うのでしょうか?

リクエストの送信中にエラーが発生するとどうなるでしょうか?例えば、誤ったデータを送信したり、誤ったエンドポイントへリクエストを送信したり、ネットワークエラーが発生したりする場合があるかもしれません。

エラーのシミュレーションを行うために、/posts/asdf というような存在しない API エンドポイントにリクエストを送信してみましょう。

このリクエストを送信すると、404 ステータスコードが返ってきます:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    // invalid url will trigger an 404 error
    axios.get(`${baseURL}/asdf`).then((response) => {
      setPost(response.data);
    }).catch(error => {
      setError(error);
    });
  }, []);
  
  if (error) return `Error: ${error.message}`;
  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

この場合、.then() コールバックを実行する代わりに、Axios はエラーを返して、.catch() コールバック関数を実行します。

この関数の中で、エラーデータを取得してステートに保存することで、エラーについてユーザーに通知します。つまり、エラーが発生したらエラーメッセージを表示します。

このコードを実行したときに、「Error: Request failed with status code 404」というテキストが見えます。

Axios インスタンスを作成する方法

これまでの例を見てみると、各リクエストを送信するために用いる Axios のエンドポイントの一部として、 baseURL があるのを確認できます。

とはいえ、すべてのリクエストに対してひとつずつ baseURL を記述し続けるのはちょっと面倒ですよね。いつも似たようなエンドポイントを含んでいるのですから、使用している baseURL を、単に Axios に覚えさせることはできないものでしょうか?

実はできます。.create() メソッドでインスタンスを作成した場合、Axios は baseURL を記憶し、さらに、すべてのリクエストに対して指定し得る、ヘッダーを含めた他の値を記憶します:

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts" 
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    client.get("/1").then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    client
      .delete("/1")
      .then(() => {
        alert("Post deleted!");
        setPost(null)
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

上のコードでは、設定用オブジェクトのプロパティーは baseURL だけであり、それにエンドポイントを渡しています。

この場合では、.create() 関数は client と呼ばれる、新しく作られたインスタンスを返します。

そうすることで、今後は、これまでと同じすべてのメソッドを用いるときに、第一引数として baseURL を渡す必要が無くなります。例えば、//1 などの必要な特定のルートを、単に参照するだけで済みます。

Axios で Async-Await 構文を使用する方法

JavaScript (React アプリケーションを含む) の中でプロミスを用いることの大きな利点は、async-await 構文が使用できることです。

async-await は、より簡潔なコードを記述できるようにしてくれます。さらに、async-await を用いたコードは、同期コードにとてもよく似ていますし、わかりやすいです。

では、どのようにして Axios で async-await 構文を用いればよいのでしょうか?

以下の例において、投稿が取得されてから、さらにその投稿を削除するボタンがあります:

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts" 
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    async function getPost() {
      const response = await client.get("/1");
      setPost(response.data);
    }
    getPost();
  }, []);

  async function deletePost() {
    await client.delete("/1");
    alert("Post deleted!");
    setPost(null);
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

ここでは useEffect の中に、getPost と呼ばれる async 関数があります。

関数を async にしたことにより、await キーワードを用いて GET リクエストを resolve させ、次の行でそのデータをステートに設定することが可能になりました。これで .then() コールバックを使わずに書くことができます。

getPost 関数が、作成された後ですぐに呼び出されていることに注意してください。

さらに、deletePost 関数も async になっています。これは、promise を resolve する await キーワードを使用するために必要です (Axios メソッドはすべて、resolve すべき promise を返します) 。

‌‌DELETE リクエストと一緒に await キーワードを使用した後で、ユーザーは投稿が削除されたことを通知され、ステートの post の値を null に設定します。

ご覧になったとおり、async-await はコードを大幅に整理し、とても簡単に、Axios と一緒に使用できます。

カスタム useAxios フックを作成する方法

async-await は、コードをわかりやすくする素晴らしい方法ですが、これをさらにもう一歩進めることができます。

コンポーネントがマウントされる際に useEffect を用いてデータを取得する代わりに、Axios で同じ処理を実行できる独自のカスタムフックを、再利用できる関数として作成できます。

カスタムフックは自分で作れますが、その一方で、use-axois-client と呼ばれるとても良いライブラリが、カスタム useAxios フックを提供しています。

まずは、パッケージをインストールします:

npm install use-axios-client

フックを使用するために、JavaScript ファイルの先頭で、use-axios-client から useAxios をインポートします。

もう useEffect は必要ないため、React のインポートは削除できます:

import { useAxios } from "use-axios-client";

export default function App() {
  const { data, error, loading } = useAxios({
    url: "https://jsonplaceholder.typicode.com/posts/1"
  });

  if (loading || !data) return "Loading...";
  if (error) return "Error!";

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  ) 
}

これで、useAxios を App コンポーネントの先頭で呼び出してから、リクエストを送信しようとしている URL を渡すことができます。また、このフックは、いろいろな状態を扱うのに必要となる、すべての値 (loadingerror、そして resolve した data) を含むオブジェクトを返します。

このリクエストの実行中は、 loading の値は true です。エラーが発生した場合は、エラー状態を表示しましょう。そうでなければ、返ってきたデータがある場合は UI (ユーザーインターフェース) の中でそれを表示できます。

このようなカスタムフックの利点は、コードを実際に削減し、全体的に簡素化できることです。

Axios でより単純にデータを取得する方法を探しているなら、試しに今回のようにカスタム useAxios フックを使ってみてください。

その次は?

おめでとうございます! 最も強力な HTTP クライアントライブラリのひとつを使用して、React アプリケーションを強化する方法を今、知ることができました。

このガイドから、多くのことを学んでいただけるよう願っています。

後で参照できるように、このガイドを PDF チートシートとしてダウンロードできることを覚えておいてください。

さらに多くの学びをご希望でしょうか? React Bootcamp にご参加ください

React Bootcamp は、Reactの学習について知っておくべきことをすべて取り入れ、ビデオ、チートシート、特別なボーナスなどを、1つのわかりやすいパッケージにまとめています。

React のプロになり、夢の仕事を得て、自分の未来を管理するために、何百人もの開発者がすでに使用している内部関係者向けの情報をこちらで手に入れてください:

react-bootcamp-1

通知を受け取るにはこちらをクリックしてください