fetch関数とaxiosの使い方

対象 fetch関数とaxiosの書き方でたまに悩む人

書いている人 プログラミング歴2年くらい

前提 非同期処理がわかる。APIを叩いたことがある。

環境 React 18.2

参考 https://zenn.dev/syu/articles/9840082d1a6633

Reactで、APIを叩く時に、axiosを使ったりfetchを使ったり両者の違いをいまいち把握していないので、GETとPOSTのやり方について、自分用にまとめる。(参考記事がかなり簡潔に書かれているのでそちらも参照してください。)

ここでは、thenで書く書き方とasync awaitを使った書き方でもそれぞれ見ていく。
※thenとasync awaitは、意味の解説ではなく、書き方の違いについて見ていきます。

非同期処理やAPIについては説明しておらず、あくまで使い方のみです。
また、ここではReactからfetchやaxiosを使っていますが、JavaScriptそのものや、JavaScriptのUIライブラリ(Vue等)ならたぶん何でも使えると思います。

非同期処理はPromiseの概念が必要になるので、もしPromiseについてよくわからなければ以下の記事も参考にしてください。

目次

JSONPlaceholderとは?

fetch関数やaxiosを使っていく前に、そもそもデータを取得してきたり、投げたりできるAPIを用意しないといけない。

ということで、JSONPlaceholderを使っていく。

JSONPlaceholderは色々な動画や記事でも見かける頻度が高いテスト用のAPIだ。

テスト用の無料のAPIだ

JSONPlaceholderのページを下にスクロールするとResourcesの欄が出てくると思う。

実際にアクセスして試してみよう。

そこに/postsとか/commentsとか書かれているがこのページにアクセスするとブラウザにたくさんのJSONデータが表示される。

/postsにアクセスしたら100件のJSONデータが返ってくる

これを実際にfetch関数やaxiosから叩くことでJSONデータを取得しよう。

もちろん、GETだけではなく全てのHTTPメソッドに対応している。今回はGETとPOSTのやり方だけ見ていくが、PUTやDELETEも余裕があれば自分で試してみよう。

全てのHTTPメソッドが使えるぞ。

fetch関数を使う

まずはfetch関数から。

fetch関数は、外部と通信を行うためにFetch APIに用意された関数だ。簡単に言うとJavaScriptを通してブラウザで使える関数のことだ。(たぶん)

外部が提供しているAPIを叩くときによく登場する。

公式より。

GETの使い方

まずは、fetch関数でGetを使った書き方から見ていこう。
thenとasync awaitでの使い方をそれぞれ記載しておく。

thenの場合

fetch関数はHTTPエラーでもrejectされないので、catchを書いても、エラーを検知できません。
この項目では簡略化のために404等のエラーをチェックするif文を書いていないので、詳しくは下の部分を見てください。

以下のAPIをfetch関数の引数で指定して、postsデータ100件をconsoleに表示させてみる。
post100件を取得してくるAPI:https://jsonplaceholder.typicode.com/posts

const App = () => {
  fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error) => console.log(error));

  return <div>APIのテストです</div>;
};

export default App;

上のコードを叩くと、consoleでpostsのJSONデータが確認できるはずだ。

100件のpostsデータがconsoleに表示された。

全くの余談だがreactのstrictモードはオンだと2回ログがでるのでオフにしておいた。

index.jsのStrictModeをコメントアウトすれば2重に表示されない

さて、fetch関数の具体的な使い方を見ていこう。

まず、fetch関数の第一引数にAPIのエンドポイントを入れる。今回だったら、JSONPlaceholderの/postsのページのURLをそのままいれてある。

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error) => console.log(error));

fetch関数の返り値はResponseオブジェクトで解決されるPromiseが返ってくる。

よくわからなかったら、とりあえずResponseオブジェクトが返ってくると思ってもらってOKだ。

日本語訳ちょっと変だけど、Responseオブジェクトで解決されるPromiseが返ってくる。
これがresponseオブジェクトの中身だ

そして、then((response) => response.json())の部分で引数に渡ってきたresponseオブジェクトをjson()メソッドを使い、さらにJSONデータで解決するPromiseを返す。

公式より。JSONで解決するPromiseを返す。

あくまで、json()メソッドはPromiseを返すので、横着して2行目でJSONデータを使うのは難しい。以下のように書いてログを見てみると、、

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => console.log(response.json()))

Promiseオブジェクトが返ってきているのがわかるはずだ。

Promiseオブジェクトが返ってきている。

なので、以下のように3行目で解決されたJSONを受け取っている。

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error) => console.log(error));

Promiseについてわからなければ、下の記事を参考にしてください。

fetch関数を使う上で1つ注意しておくことがある。エラーハンドリングについてだ。

fetch関数は404などのHTTPステータスエラーが起きても、エラーを返さないのでcacthでエラーを捕捉することができない。なのでresponseのステータスやresponse.okなどをif文などで確認する必要がある。

fetch関数は404はエラーにならない。

以下の3~6行目で、response.okを確認してこの値がtrueでなかった場合はエラーを投げるように処理をさせる。

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => {
      if (!response.ok) {
        throw new Error("エラーです!!");
      }
      return response.json();
    })
    .then((json) => console.log(json))
    .catch((error) => console.log(error));

これで、404が発生すると以下のようにエラーが投げられる。

postsをpotsに変更させ404を発生させた。

fetch関数を使う時は、404をcatchできるようにif文で処理を記述してあげよう。

async awaitの場合

次はasync awaitで書いた場合だ。こちらを使うとthenよりもすっきりと書くことができて、かなりコードが見やすい。

asyncはプロミスの上に成り立っている。よりすっきり書けるよと公式にも記載されている。

以下がthenで書くものから、async awaitに変更したものだ。

async function getPosts() {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    if (!response.ok) {
      throw new Error("エラーです!!");
    }
    const data = await response.json();
    console.log(data);
  }
  getPosts();

asyncは非同期関数を明示するものなので、関数の前にキーワードしてasyncと書く。そして、中でawaitを使って結果の値が返ってくるまで待つことができる。関数として定義しただけなので、発動するのを忘れないようにしよう。

もちろん、以下のようにアロー関数でも記述することができる。

const getPosts = async () => {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    if (!response.ok) {
      throw new Error("エラーです!!");
    }
    const data = await response.json();
    console.log(data);
  };
  getPosts();

こちらもthenの時と同様に、if文でresponseを判断して404が帰ってきてもエラーを捕捉してあげよう。

404でも拒否されない!

try catch文

上のやり方で404系はエラーを吐かせることができたが、サーバーのエラーを検知することができない。(500系のエラー)
通常async awaitでエラーを検知する時は、try catch文をよく使う。thenの.catchに当たる部分だ。

try catchを使って上の文を書き換えていこう。

const getPosts = async () => {
    try{
      const response = await fetch("https://jsonplaceholder.typicode.com/posts");
      if (!response.ok) {
        throw new Error("エラーです!!");
      }
      const data = await response.json();
      console.log(data);
    }
    catch(error){
      console.log(error);
    }

tryの中に非同期の処理、catchの中にエラー時の処理を記述するだけだ。

ちなみに、asyncを使った場合、返り値がPromiseなのでtry catchを使わずに、非同期関数にメソッドチェーンでcatch()を使ってのエラーハンドリングも可能だ。

  getPosts().catch(error => console.log(error));

こっちの方が見やすいかも?

POSTの使い方

次は、fetch関数を使ったPOSTの処理についてだ。

以下のJSONPlaceholder公式のメソッドをそのまま使ってみる。

JSONPlaceholder公式から。

このfetchの処理をそのまま走らせると、以下のようなログが返ってくる。注目してほしいのはidの部分。JSONPlaceholderに用意されたpostsはid100番まで、つまりPOSTを走らせることによって、新しいオブジェクトを作成することができた。

idが101になっている。

ただし、JSONPlaceholderに用意されているpostsが実際に増えるわけではなく、あくまでフェイクとして追加されただけだ。

実際のpostsはid100番まで

コードを詳しくみていこう。

  fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    body: JSON.stringify({
      title: "foo",
      body: "bar",
      userId: 1,
    }),
    headers: {
      'Content-type': 'application/json; charset=UTF-8',
    },
  })
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      console.log(data);
    })
    .catch((error) => {
      console.log(error);
    });

2行目から10行目がGETの時と違う部分だ。POSTを使うには、fetch関数の第二引数でオブジェクトをいくつか設定する必要がある。それぞれ見ていこう。

公式より。fetch関数の第二引数にはカスタム設定のオブジェクトを設定する。
  • methodプロパティ
    オブジェクトの1つはmethodプロパティで、ここをPOSTに設定してあげる。ここでは紹介しないが、PUTやDELETEといった処理を行うときも、このプロパティに明示的に記述する必要がある。
  • bodyプロパティ
    ここには追加したいデータを用意する。JavaScriptのオブジェクトの形式で記述して、それをJSON.strigify()メソッドを使ってJSON形式に変換する必要がある。今回は公式通り、title,body,userIdの各プロパティにfoo,bar,1といったデータを付け加えた。
//作成したいデータ
body: JSON.stringify({
      title: "foo",
      body: "bar",
      userId: 1,
    }),
JSON.stringifyメソッドを使って、オブジェクトをJSON形式のデータに変換する。
  • headersプロパティ
    ここには、bodyに用意したデータがどのようなデータ形式なのかを示してあげる。JSONデータで送ったので、application/jsonと記述しよう。
headers: {
      'Content-type': 'application/json; charset=UTF-8',
    },

ちなみにheadersプロパティを用意しなかったら、以下のようにデータの中身が反映されなかったのでしっかり記述してあげる必要がある。charset=UTF-8も書かないとうまく反映されなかったので記述しておこう。

idだけは追加されてるっぽい

async awaitの場合

POSTの場合もGETと同じくasync awaitに書き換えることができる。try catchでエラーハンドリングしながら書いていく。

const pushPosts = async () => {
    try {
      const posts = await fetch("https://jsonplaceholder.typicode.com/posts", {
        method: "POST",
        body: JSON.stringify({
          title: "foo",
          body: "bar",
          userId: 1,
        }),
        headers: {
          "Content-type": "application/json; charset=UTF-8",
        },
      });
      const data = await posts.json();
      return console.log(data);
    } catch (error) {
      console.log(error);
    }
  };
  pushPosts();

tryの中に非同期処理を書いて、catchにエラー処理を書くだけだ。

ここでは省略の為に404系のエラーを検知していないが、検知したい時は、if文でstatus等を判断してあげよう。

axiosを使う

次は、axiosの使い方を見ていこう。
axiosはライブラリなので、さきにnpmyarnを使ってaxiosをインストールしておこう。

axiosライブラリ:https://www.npmjs.com/package/axios

自身で使用しているパッケージマネージャに合わせてaxiosをインストールしよう。

fetch関数と違って、axiosにするとコードの量を少し削減できるのでさっそく使い方を見ていこう。

GETの使い方

まずはGETのやり方。

以下がaxiosを使った場合の書き方だ。axiosからgetメソッドを呼んでその中でAPIを指定している。

import axios from "axios";

axios
    .get("https://jsonplaceholder.typicode.com/posts")
    .then((response) => response)
    .then((response) => console.log(response.data))
    .catch((error) => console.log(error));
axiosでも同じようにデータが取得できる。

fetchの場合は、エラーをcatchで検知することができなかったが、axiosの場合404などのエラーは自動的に検知してくれる。
以下のように、URLを変更して意図的に404を起こしてみよう。

import axios from "axios";

axios
    .get("https://jsonplaceholder.typicode.com/pots") //URLをposts->potsに変更して404を意図的に起こさせる
    .then((response) => response)
    .then((response) => console.log(response.data))
    .catch((error) => console.log(error));

意図的にエラーを起こしても、以下のようにcatchで捕捉されて、エラーオブジェクトが吐き出される。

if文でstatusを確認しなくてもエラーを検知できた。

また、axiosの場合は返ってきたresponseに対して、response.json()を使わなくてもresponse.dataで中身を取得できる。

async awaitの場合

次にaxiosで、async awaitを使って記述してみる。

  const getPosts = async () => {
    try {
      const response = await axios.get(
        "https://jsonplaceholder.typicode.com/posts"
      );
      const data = await response.data;
      console.log(data);
    } catch (error) {
      console.log(error);
    }
  };
  getPosts();

try catch文を使ってエラーハンドリングをしつつ、async awaitを使用している。

thenでもasync awaitでも自分が好きな方を使おう。

Reactなどで使う場合は、import axios from "axios";を書くのを忘れないようにしておこう。

POSTの使い方

次に、axiosを使った場合のPOSTについて見ていこう。POSTの方がGETよりもだいぶコードを省略できるのでaxiosを使った恩恵が見られるかもしれない。

以下がaxiosでPOSTを使った時の書き方だ。

const pushPosts = async () => {
    axios
      .post("https://jsonplaceholder.typicode.com/posts", {
        title: "foo",
        body: "bar",
        userId: 1,
      })
      .then((response) => {
        console.log(response.data);
      })
      .catch((error) => {
        console.log(error);
      });
  };
  pushPosts();

axiosからpostメソッドを呼んで、中でAPIとデータを用意している。fetch関数と大きく違うのは、第二引数はデータ(オブジェクト)だけでよいということだ。
fetch関数では第二引数にオブジェクトを用意して、methodプロパティを明示的に記述したり、JSON.stringifyメソッドを使ってオブジェクトをJSON形式に変換しなくてはならなかった。

だいぶ書き方が簡潔になったのがわかると思う。

async awaitの場合

async awaitを使った書き方は以下になる。try catchを使ってエラーハンドリングしている。

const pushPosts = async () => {
    try {
      const response = await axios.post(
        "https://jsonplaceholder.typicode.com/posts",
        {
          title: "foo",
          body: "bar",
          userId: 1,
        }
      );
      console.log(response.data);
    } catch (error) {
      console.log(error);
    }
  };
  pushPosts();

こちらも、特に大きな違いは見られないだろう。

まとめ

各使い方を見てきたので、axiosとfetchの差異についてまとめておく。

スクロールできます
fetchaxios
if文でresponseのstatus等の管理必要必要なし
POSTの際オブジェクトを用意必要必要なし
dataをJSON形式にする必要必要なし
axiosの方が色々省略できそうだ。

こんなところだろうか。

axiosを使った方が、コードの量も削減できるのでおすすめだが、fetchのことも理解しておくことでどちらにも対応できるようになるのでどちらも書けるようにしておこう。
axiosはまだまだ他の使い方がありそうなので、機会があればまとめたい。

少しでも理解が深まってくれていれば、ありがたいです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次