宣言型データフェッチのためのReact-Asyncライブラリの使用
序章
JavaScriptアプリケーションでデータをフェッチする場合、async-await
を使用すると、命令型同期プログラミングを使用してデータをフェッチできます。 これは、私たちのコードが、プログラムがどのように機能し、単一の操作スレッドに沿って動作するかを必須に記述していることを意味します。 一方、Reactは、UIを宣言的に構築するライブラリです。 これは、命令型プログラミングとは反対の方法であると見なされることがよくあります。この方法では、開発者は、プログラムの動作方法ではなく、プログラムに実行させたいことを記述します。 したがって、Reactとasync-await
の組み合わせは、命令型コード(データフェッチ用)と宣言型コード(UI構成用)の両方を持つ混合パターンになります。
React-async は、単一のReactコンポーネントを使用してREST API呼び出しを実行する宣言型APIを提供し、アプリケーション全体で宣言型プログラミングを使用できるようにします。 エラーの処理、Promiseの解決、Promiseの再試行を処理し、ローカルの非同期状態を処理します。
この記事では、React-Asyncライブラリがデータのフェッチにどのように役立つかを説明し、ヘルパーのコンポーネントと関数のいくつかのデモンストレーションを実行します。
React-Asyncを使用して宣言的にデータをフェッチする
トピックを2つの部分に分けてみましょう。Reactでの宣言型データフェッチと非同期API呼び出しです。
宣言型データフェッチは、APIの呼び出しで使用されるアプローチであり、呼び出しに関連するすべてのことを気にせずに、実行したいことを宣言します。 これは、プログラムに実行させたい手順を詳細に説明する必要がある命令型アプローチの反対です。
JavaScriptはデフォルトで同期であり、シングルスレッドであるため、以前のバージョンのReactで非同期呼び出しからのデータを表示するコンポーネントをレンダリングする場合は、クラスを使用する必要がありました。 コンポーネントのライフサイクルメソッドを使用して、コンポーネントがマウントされたときに呼び出しが発生するようにする必要がありました。次に、ローカル状態を使用してロード状態を管理しました。
非同期リクエストは、残りのコードが実行されている間、リクエストが応答するのを待ちます。 次に、適切なタイミングで、コールバックがこれらの非同期要求を実行に移します。
エンドポイントを呼び出して通貨価格のリストを取得することにより、これを示しましょう。
import React, { Component } from 'react'; import axios from 'axios'; class App extends Component { state = { data: [], error: '', }; componentDidMount() { axios .get('https://api.coinmarketcap.com/v1/ticker/?limit=1') .then(res => this.setState({ data: res.data })) .catch(error => this.setState({ error })); } render () { return ( <div className="App"> <ul> {this.state.data.map(el => ( <li> {el.name}: {el.price_usd} </li> ))} </ul> </div> ); } } export default App;
注:端末に「npminstallaxios」と入力してaxiosをインストールします。
このコードは、このCodeSandboxページを使用してライブで確認できます。
ここでは、 componentDidMount 関数でAPI呼び出しを行い、コンポーネントが読み込まれるとすぐに実行されるようにします。 次の手順を実行した後でのみ、データを理解できます。
- まず、APIにリクエストを送信します。
- その後、応答を受け取ります。
- 応答からデータを抽出します。
- 最後に、データをローカル状態で保存します。
データフェッチプロセス中にエラーが発生した場合:
- エラーをキャッチします。
- 次に、データをローカル状態に保存します。
ここでは、データをフェッチするすべてのステップでどのように何をすべきかを明示的に説明しています。 構文と関数は正しく機能しますが、宣言的に記述した場合、コードをより効率的に、より少ない行で書き直すことができます。 React-Asyncを使って書き直してみましょう。
まず、ターミナルにnpm install react-async
と入力してパッケージをインストールする必要があります。 次に、次のコードを使用してコンポーネントを記述します。
import React, { Component } from 'react'; import Async from 'react-async'; const loadJson = () => fetch("https://api.coinmarketcap.com/v1/ticker/?limit=1") .then(res => (res.ok ? res : Promise.reject(res))) .then(res => res.json()) const App = () => ( <Async promiseFn={loadJson}> {({ data, error, isLoading }) => { if (isLoading) return "Loading..." if (error) return ``Something went wrong: ${error.message}`` if (data) return ( <div> {data.map(el => ( <li> {el.name}: {el.price_usd} </li> ))} </div> ) return null }} </Async> ) export default App;
CodeSandboxを使用している場合は、依存関係メニューからReact-Asyncを追加します。 このコードをライブで見たい場合は、CodeSandboxのReact-Asyncの例をご覧ください。
ここでは、クラスの代わりにフックを使用してコンポーネントを書き直しました。 まず、データフェッチを処理する関数loadJson
を作成します。 次に、Appコンポーネント内で、React-Asyncライブラリから利用できるAsync
コンポーネントを利用します。
約束が解決されると、さまざまなシナリオを処理するための小道具が利用できるようになります。
isLoading
が利用可能であるため、データがまだロードされていないときにユーザーフレンドリーなメッセージを表示できます。error
は、フェッチ中にエラーが発生した場合に使用できます。data
は、フェッチが完了した後に返される実際のデータです。
この例では、データをロードするためにクラスやライフサイクルメソッドを使用する必要はなく、データの処理方法や状態の更新方法をReact-Asyncに指示する必要もありません。
React-Asyncは、isLoading
フォールバックプロップを介して読み込み状態を管理します。フォールバックプロップは、data
をレンダリングする準備ができるまで、つまり、依存する非同期呼び出しが解決してデータを返すまでレンダリングされます。
ヘルパーコンポーネント
React-Asyncには、JSXをより宣言的で整理されたものにするいくつかのヘルパーコンポーネントが付属しています。 各ヘルパーコンポーネントは、適切な場合にのみ子をレンダリングします。 App関数を次のように書き直すことができます。
const App = () => ( <Async promiseFn={loadJson}> <Async.Loading>Loading...</Async.Loading> <Async.Resolved> {data => ( <div> {data.map(el => ( <li> {el.name}: {el.price_usd} </li> ))} </div> )} </Async.Resolved> <Async.Rejected> {error => `Something went wrong: ${error.message}`} </Async.Rejected> </Async> )
CodeSandboxでこの例を確認してください。
この例では、Async.Loading
、Async.Resolved
、およびAsync.Rejected
関数を使用して、コードを簡略化し、読みやすくしています。 React-Asyncによって提供されるヘルパーコンポーネントは、React要素または関数を子として受け取ることができます。 関数を提供すると、コンポーネントで使用できるレンダリングプロップを受け取ります。
ヘルパー機能を備えたユーザープロファイルテストアプリ
さらにいくつかのヘルパー関数を使用する小さなユーザープロファイルアプリを作成しましょう。 コンポーネントを次のコードに更新します。
import React, { Component } from 'react'; import Async from 'react-async'; const loadUser = ({ userId }) => fetch('`https://reqres.in/api/users/${userId}'`) .then(res => (res.ok ? res : Promise.reject(res))) .then(res => res.json()) const UserPlaceholder = () => ( <div> <div>User Details Loading</div> </div> ) const UserDetails = ({ data }) => ( <div className="details"> <img className="avatar" src={data.data.avatar} alt="" /> <div> {data.data.first_name} {data.data.last_name} </div> </div> ) const App = () => ( <Async promiseFn={loadUser} userId={1}> <Async.Pending> <UserPlaceholder /> </Async.Pending> <Async.Fulfilled>{data => <UserDetails data={data} />}</Async.Fulfilled> <Async.Rejected>{error => <p>{error.message}</p>}</Async.Rejected> </Async> ) export default App;
宣言した関数を見てみましょう。
loadUser
:データフェッチを処理するためにこの関数を定義します。 小道具(userId
)を受け取り、IDに基づいてAPIをクエリします。userPlaceholder
:これは、Promiseがまだ解決されていない場合、つまりデータの読み込みが完了していない場合に表示されるフォールバックコンポーネントです。userDetails
:このコンポーネントは、ユーザーデータの実際の表示を処理します。 小道具を介してデータを取り込み、promiseが解決された場合にのみレンダリングされます。Async.Pending
、Async.Fulfilled
、およびAsync.Rejected
:これらは、コードを単純化して読みやすくするための関数です。
結論
このチュートリアルでは、React-Asyncライブラリを使用してデータを宣言的にフェッチする方法について説明しました。 また、それが提供するヘルパー関数のいくつかも調べました。 React-Asyncの詳細については、GitHubのReact-Asyncドキュメントをご覧ください。