Reactフックを使用したAsync/Awaitを用いたAPI呼び出しの実装方法
はじめに
React開発者の皆さん、こんにちは!本日はuseEffectフックとasync関数の適切な使い方についてお話しします。これらの機能を理解し、正しく活用することで、より効果的なコーディングが可能になりますので、是非参考にしてみてください。
以前の記事では、Reactフックを利用してFetchメソッドを使い、非同期処理にasync/awaitを使用せずにAPI呼び出しを行う方法を解説しました。
「Reactフックを使ったAPI取得の方法 | 簡単な手順で実装可能 - deve.K's Programming Primer - プログラミング初心者のための入門ブログdev-k.hatenablog.com
しかし、一般的には外部リソースへのアクセスにはFetchを用い、async/await構文を使って非同期処理を行う必要があります。
今回は、ReactのuseEffectフックとuseStateフックを使ってasync/awaitを導入し、API呼び出しを処理する方法を簡単なコード例を交えて解説します。
なお、事前にuseEffectとuseStateフックの基本的な理解を前提としています。
Fetchメソッド
Fetchは、シンプルなインターフェースを提供してリソースを取得する手段です。
このAPIを利用することで、ネットワークリクエストとレスポンスの処理が、従来のXMLHttpRequest(XHR)よりも簡単に行えます。
Fetch APIは、Promisesを活用する特徴があります。これにより、コールバック地獄や冗長なコードを避けることができます。
従来のXMLHttpRequest(XHR)とは異なり、Fetchを利用することで、非同期処理をよりスマートに行えるのです。これは、ブラウザやサーバーとの間でデータをやり取りする際に非常に便利です。
Fetch関数は、フェッチするリソースのパスを1つの引数として受け取ります。そして、そのリクエストに対する応答を解決するPromiseを返します。
Promiseは、非同期操作の成功や失敗を処理するための手段であり、コールバックを効果的に管理することができます。
こうしたFetch APIの利点により、開発者はよりスマートで効率的なコードを書くことができます。
これによって、アプリケーションのパフォーマンスが向上し、ユーザーエクスペリエンスが向上するでしょう。
Promiseについては以下で解説しておりますので参考にしてみてください。
ReactフックでFetchAPIとPromisesの使用
Reactの最新のフロントエンド開発において、APIエンドポイントからデータを取得してユーザーリストをレンダリングする方法について、詳細な手順を紹介します。
これにより、ReactのuseEffectフックとFetchAPIとPromisesの強力な機能を活用し、シンプルで効率的なコードを実現できます。
まず、Reactコンポーネント内でuseEffectフックを使用します。
useEffectフックは、コンポーネントのライフサイクルにフックして特定の動作をトリガーするために使用されます。
useEffectは、コンポーネントのライフサイクルにフックして、副作用を実行するための強力な機能です。
このフックの第2引数に空の配列を渡すことで、コンポーネントのマウント時に一度だけ実行されるようにします
import { useEffect } from "react"; const App = () => { useEffect(() => { // ページにアクセスしたらここでAPIを呼び出す }, []); return <div></div>; };
次に、APIを呼び出すURLを定義します。
ここでは、JSON PlaceholderのREST APIであるhttps://jsonplaceholder.typicode.com/users
を使用します。
これはダミーデータを提供してくれる便利なAPIです。
import { useEffect } from "react"; const App = () => { useEffect(() => { const url = "https://jsonplaceholder.typicode.com/users"; // ここでAPIを呼び出す処理を追加する }, []); return <div></div>; };
APIを呼び出すためにはFetchAPIを使用します。
FetchAPIはネットワークリクエストを行うための標準的な方法であり、非同期処理をPromisesを通じて扱うことができます。
次のステップで、データを取得するためのリクエストを作成し、レスポンスをJSON形式で解析してユーザーリストを取得していきましょう。
async関数の作成
データをfetchするための、async関数を作成していきます。
async関数は、Promiseが解決された後、続行する前に待機する必要がある関数となります。
useEffectフックでは、コンポーネントがマウントされた後にデータを取得するようにします。
useEffect(() => { const url = "https://jsonplaceholder.typicode.com/users"; const fetchUsersData = async () => { try { const res = await fetch(url); const json = await res.json(); console.log(json); } catch (e) { console.log("error", e); } } fetchUsersData(); //呼び出し }, []);
fetchUsersData関数をuseEffectフック内に入れて呼び出します。
try { const res = await fetch(url); const json = await res.json(); console.log(json); } catch (e) { console.log("error", e); }
fetchUsersDataという非同期関数を定義しています。
この関数では、try...catch文を使用してエラーハンドリングを行っています。これにより、ネットワークエラーやAPIの問題などが発生した場合でも、アプリがクラッシュすることを防ぐことができます。
fetch関数を使ってデータを取得した後、res.json()メソッドを使用してレスポンスをJSON形式に変換しています。
このメソッドは非同期関数であり、awaitキーワードを用いて結果を待つように指定しています。これにより、非同期処理が完了するまで次の行の実行を待つことができます。
取得したJSONデータは、コンソールに表示されます。
コンソールの出力はcodepen.io/enjinia_f/demoで確認できます。
このようにして、データの取得が正常に行われたかどうかを確認することができます。
全体コードは以下となります。
import React, { useEffect } from 'react'; const App = () => { useEffect(() => { // データを取得するURL const url = "https://jsonplaceholder.typicode.com/users"; // データを非同期に取得する関数 const fetchUsersData = async () => { try { // fetch APIを使ってデータを取得 const res = await fetch(url); // レスポンスをJSON形式に変換 const json = await res.json(); // 取得したデータをコンソールに表示 console.log(json); } catch (e) { console.log("エラーが発生しました", e); } } // データを取得する関数を呼び出す fetchUsersData(); }, []); return ( <div> {/* コンポーネントの中身 */} </div> ); } export default App;
非同期関数を使用することで、データの取得が非同期的に行われるため、ユーザーエクスペリエンスが向上します。
データの取得が完了するまで、アプリケーションが固まることなく、ユーザーはスムーズな操作を行うことができます。
以上のコード例を参考にして、Reactアプリケーションで非同期処理を上手に活用し、ユーザーフレンドリーなアプリケーションを開発してみてください。
データの取得に関するエラーハンドリングも忘れずに行うことで、アプリケーションの安定性を高めることができます。
ReactでAPIからユーザーデータを取得して表示する方法
Reactアプリケーションを作成する際、外部APIからデータを取得して表示する必要があることがよくあります。
ReactのuseStateフックとuseEffectフックを使用して、外部APIからユーザーデータを取得し、ブラウザに表示する方法について説明します。
まず、コンポーネントの最上部でuseStateフックを使い、usersという状態とその更新用の関数setUsersを定義します。
const App = () => { const [users, setUsers] = useState([]) useEffect(() => { const url = "https://jsonplaceholder.typicode.com/users";
useStateフックを使ってusersという空の配列を初期値として定義しています。これは後ほどAPIから取得したユーザーデータを格納するための状態として利用されます。
次に、useEffectフックを使って外部APIからユーザーデータを取得します。
ここでは、https://jsonplaceholder.typicode.com/users
というURLからデータを取得する例を示します。
useEffect(() => { const fetchUsers = async () => { const url = "https://jsonplaceholder.typicode.com/users"; try { const res = await fetch(url); const json = await res.json(); setUsers(json); console.log(json); } catch (e) { console.log("error", e); } }; fetchUsers(); }, []);
useEffectフック内で非同期のfetchUsers関数を定義し、その中でAPIへのGETリクエストを行っています。
取得したデータはjsonとして保存され、setUsers関数を使ってusersの状態を更新しています。
そして、map関数を使ってusersの中身を繰り返し処理し、リスト形式でブラウザに表示しています。
return ( <div> <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> </div> ); }; export default App;
See the Pen React fetch async/await APIからデータ取得 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
これでReactアプリケーションが起動した際に、APIから取得したユーザーデータがリストとして表示されるようになります。
非同期処理を行うためにuseStateフックとuseEffectフックを組み合わせることで、スムーズなユーザーエクスペリエンスを提供することができます。
条件付きtryブロックのエラー処理
useStateフックと条件付きtryブロック、そして条件付き三項演算子を使ったデータ取得とエラーハンドリングについて説明します。
まず、useStateフックの初期値としてfalseを設定します。
const App = () => { const [users, setUsers] = useState([]) const [isError, setIsError] = useState(false); useEffect(() => { const url = "https://jsonplaceholder.typicode.com/users";
次に、fetch関数を使ってデータを取得し、条件付きtryブロックを作成します。
try { const res = await fetch(url); if (res.ok) { const json = await res.json(); setUsers(json); } else { throw "エラー"; }
ここで、okプロパティを使ってリクエストが成功したかどうかを確認しています。
okプロパティは、Responseオブジェクトに含まれるもので、ステータスコードが200〜299の範囲であればtrueを返し、それ以外のステータスコードではfalseとなります。
もちろん、同じチェックをHTTPステータスコードの200で行うこともできますが、今回はokプロパティを使用しています。
if(res.status === 200)
最後に、条件付き三項演算子を使ってエラーメッセージを表示します。。
return ( <div> {isError ? <h2>Warning: Error! もう一度、お試し下さい。</h2> : <ul> {users.map((user) => <li key={user.id}> {user.name} </li>)} </ul> } </div> );
isErrorは初期値でfalseとなっているため、条件付きtryブロックが正常に実行された場合は、ul要素内でmap関数を使ってユーザーのリストが表示されます。
See the Pen React fetch async/await 条件付きtryブロック エラー処理 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
もちろん、okプロパティを否定論理(!)で反転させることもできます。
try { const res = await fetch(url); if(!res.ok){ const json = await res.json(); setUsers(json) }else { throw "Erorr" }
否定論理で反転されたokプロパティは、ステータスコードが200〜299の範囲では結果がfalseとなります。
See the Pen React async/await 条件付きtryブロック エラーの例 エラー処理 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
これらを、カスタムフックとして再利用する方法は、カスタムフックの基礎に精通する必要があります。
カスタムフックについては以下で解説しておりますので参照下さい。
これで、useStateフックと条件付きtryブロック、条件付き三項演算子を使ってデータの取得とエラーハンドリングを行う方法をご紹介しました。
これらのテクニックを上手に活用して、より堅牢でユーザーフレンドリーなReactアプリケーションを作成してください!お疲れ様でした!。
他のReact開発者たちから悲鳴を聞かないために知っておきたいポイント
useEffectフックを使ったデータ取得についてお話ししますが、注意が必要な一つの間違いについてご紹介します。
この誤った方法を使用すると、他のReact開発者たちから悲鳴が聞こえるかもしれません。
まず、間違った例を見てみましょう。
// これはやめて useEffect(async () => { const data = await fetchData(); }, [fetchData]);
ここでの問題は、useEffectの最初の引数が、何も返さない(undefined)か、またはクリーンアップのために関数を返す必要がある場合に、async関数が使われていることです。
async関数はPromiseを返すため、useEffectが期待する形式とは異なります。
このような記述は、useEffectフックには適していないのです。
正しい書き方は以下の通りです。
useEffect(() => { const fetchData = async () => { try { const data = await fetch('https://xxxx.com'); // データの処理やstateの更新などを行う } catch (error) { console.error(error); } }; fetchData(); // 関数を呼び出す }, []);
上記のように、async関数はuseEffectの内部に記述し、fetchData関数を直接呼び出すことでデータの取得を行います。また、エラーハンドリングも適切に行いましょう。
もし、データ取得関数をuseEffectの外に置きたい場合は、useCallbackフックを使って関数をラップすることができます。
つまり、関数内で非同期処理を直接実行する場合には、注意してください。
useEffect(() => { async function fetchData() { const data = await fetch('https://example.com/api/data'); // データの処理やstateの更新など } fetchData(); // このような書き方は誤りです }, []);
上記の例では、関数内で非同期処理を直接実行していますが、これはコンポーネントがマウントされるたびに毎回非同期処理が実行されてしまう問題があります。
正しいやり方は、関数をuseCallbackフックでラップしておき、依存リストにその関数を指定して実行タイミングをコントロールすることです。
以下にその例を示します。
import { useEffect, useCallback } from 'react'; function YourComponent() { const fetchData = useCallback(async () => { const response = await fetch('https://example.com/api/data'); const data = await response.json(); // データの処理やstateの更新など }, []); useEffect(() => { fetchData(); // マウント時に非同期処理を実行 }, [fetchData]); // fetchData関数を依存リストに指定 // 他のコンポーネントのレンダリングなど return ( <div> {/* コンポーネントの中身 */} </div> ); }
このようにすることで、コンポーネントがマウントされた時にのみ非同期処理が実行され、以降の再レンダリングでは非同期処理が再度実行されることはありません。
useCallbackフックによってfetchData関数はコンポーネントのインスタンスが変わることなくキャッシュされ、依存リストにfetchDataを指定することで、fetchDataが更新された場合にのみuseEffect内のコールバックが実行されるようになります。
注意点として、useCallbackを必ずしも使う必要はなく、useEffect内で直接非同期関数を呼び出すことも問題ありません。
useCallbackは、特定の関数を依存リストに指定して、それが変更されたときだけ再度実行したい場合に便利です。
useCallbackフックの解説は以下で解説しております。
そして最後に、非同期処理のエラーハンドリングが不足している場合です。
useEffect(() => { async function fetchData() { const response = await fetch('https://example.com/api/data'); const data = await response.json(); // データの処理やstateの更新など } fetchData(); // エラーハンドリングが不足している }, []);
上記の例では、fetchでの非同期処理にエラーハンドリングが含まれていません。非同期処理は常にエラーの可能性があるため、try-catchブロックを使ってエラーを適切にハンドリングすることが重要です。
これらの間違った例を避けるために、正しい使い方について理解し、コードを適切に構造化することが重要です。データ取得においては、非同期処理とエラーハンドリングに特に注意を払うよう心がけましょう。
皆さんのReactアプリケーションがスムーズに動作するように、適切な方法でuseEffectフックを活用してください。
素晴らしいコーディングをお楽しみください!
最後に
データ取得において非常に便利なpromise.all()を活用することで、並列で待機を行うことが可能です。これにより、効率的なデータ取得が実現できます。
また、useEffectフックを使う際には常にクリーンアップ関数を提供するように心掛けましょう。これにより、不要なリソースの解放やメモリリークの防止が行えます。
さらに、useEffectフック内でのasync関数の利用に関しては、注意が必要です。正しく使うためには、useEffect内部でasync関数を定義し、それを実行する形でデータのフェッチを行う必要があります。
データのフェッチには様々な方法がありますが、useEffectフックとasync関数を適切に活用することで、コードの可読性や保守性を高めることができます。
初心者の方々に向けて、useEffectフックでのasync関数の正しい使い方をご紹介しました。新しいプロジェクトで試してみる際は、ぜひこのアドバイスを参考にしてみてください。
お読みいただき、ありがとうございました。
この記事が役に立ったら、ブックマークと共有をしていただけると幸いです。
それでは、良いコーディングをお楽しみください。