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だ。
JSONPlaceholderのページを下にスクロールするとResourcesの欄が出てくると思う。
そこに/postsとか/commentsとか書かれているがこのページにアクセスするとブラウザにたくさんのJSONデータが表示される。
これを実際にfetch関数やaxiosから叩くことでJSONデータを取得しよう。
もちろん、GETだけではなく全てのHTTPメソッドに対応している。今回はGETとPOSTのやり方だけ見ていくが、PUTやDELETEも余裕があれば自分で試してみよう。
fetch関数を使う
まずはfetch関数から。
fetch関数は、外部と通信を行うためにFetch APIに用意された関数だ。簡単に言うとJavaScriptを通してブラウザで使える関数のことだ。(たぶん)
外部が提供しているAPIを叩くときによく登場する。
GETの使い方
まずは、fetch関数でGetを使った書き方から見ていこう。
thenとasync awaitでの使い方をそれぞれ記載しておく。
thenの場合
以下の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データが確認できるはずだ。
全くの余談だがreactのstrictモードはオンだと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だ。
そして、then((response) => response.json())
の部分で引数に渡ってきたresponseオブジェクトをjson()メソッド
を使い、さらにJSONデータで解決するPromiseを返す。
あくまで、json()メソッド
はPromiseを返すので、横着して2行目でJSONデータを使うのは難しい。以下のように書いてログを見てみると、、
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => console.log(response.json()))
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文などで確認する必要がある。
以下の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が発生すると以下のようにエラーが投げられる。
fetch関数を使う時は、404をcatchできるようにif文で処理を記述してあげよう。
async awaitの場合
次はasync awaitで書いた場合だ。こちらを使うとthenよりもすっきりと書くことができて、かなりコードが見やすい。
以下が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が帰ってきてもエラーを捕捉してあげよう。
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公式のメソッドをそのまま使ってみる。
このfetchの処理をそのまま走らせると、以下のようなログが返ってくる。注目してほしいのはidの部分。JSONPlaceholderに用意されたpostsはid100番まで、つまりPOSTを走らせることによって、新しいオブジェクトを作成することができた。
ただし、JSONPlaceholderに用意されているpostsが実際に増えるわけではなく、あくまでフェイクとして追加されただけだ。
コードを詳しくみていこう。
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関数の第二引数でオブジェクトをいくつか設定する必要がある。それぞれ見ていこう。
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,
}),
headers
プロパティ
ここには、bodyに用意したデータがどのようなデータ形式なのかを示してあげる。JSONデータで送ったので、application/json
と記述しよう。
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
ちなみにheaders
プロパティを用意しなかったら、以下のようにデータの中身が反映されなかったのでしっかり記述してあげる必要がある。charset=UTF-8
も書かないとうまく反映されなかったので記述しておこう。
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にエラー処理を書くだけだ。
axiosを使う
次は、axiosの使い方を見ていこう。
axiosはライブラリなので、さきにnpm
やyarn
を使ってaxiosをインストールしておこう。
axiosライブラリ:https://www.npmjs.com/package/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));
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で捕捉されて、エラーオブジェクトが吐き出される。
また、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でも自分が好きな方を使おう。
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の差異についてまとめておく。
fetch | axios | |
---|---|---|
if文でresponseのstatus等の管理 | 必要 | 必要なし |
POSTの際オブジェクトを用意 | 必要 | 必要なし |
dataをJSON形式にする | 必要 | 必要なし |
こんなところだろうか。
axiosを使った方が、コードの量も削減できるのでおすすめだが、fetchのことも理解しておくことでどちらにも対応できるようになるのでどちらも書けるようにしておこう。
axiosはまだまだ他の使い方がありそうなので、機会があればまとめたい。
少しでも理解が深まってくれていれば、ありがたいです。