ReactアプリでApollo-Clientを使用してクライアント側のGraphQlを理解する
公開: 2022-03-10State of JavaScript 2019によると、開発者の38.7%がGraphQLを使用したいと考えており、開発者の50.8%がGraphQLを学びたいと考えています。
クエリ言語であるGraphQLは、クライアントアプリケーションを構築するワークフローを簡素化します。 必要なデータをフェッチするための単一のHTTPエンドポイントを公開するため、クライアント側アプリでのAPIエンドポイントの管理の複雑さが解消されます。 したがって、RESTの場合のように、データのオーバーフェッチとアンダーフェッチが排除されます。
しかし、GraphQLは単なるクエリ言語です。 それを簡単に使用するために、私たちは私たちのために重い物を持ち上げるプラットフォームが必要です。 そのようなプラットフォームの1つがApolloです。
Apolloプラットフォームは、クラウド(サーバー)間でアプリのUIにデータを転送するGraphQLの実装です。 Apollo Clientを使用する場合、データの取得、追跡、ロード、およびUIの更新のためのすべてのロジックは、 useQuery
フックによってカプセル化されます(Reactの場合のように)。 したがって、データフェッチは宣言型です。 また、ゼロ構成キャッシングも備えています。 アプリでApolloClientを設定するだけで、追加の構成を必要とせずに、すぐに使用できるインテリジェントキャッシュを利用できます。
Apollo Clientは、Angular、Vue.js、Reactなどの他のフレームワークとも相互運用可能です。
注:このチュートリアルは、過去にクライアント側でRESTfulまたは他の形式のAPIを使用したことがあり、GraphQLを試してみる価値があるかどうかを確認したい人に役立ちます。 これは、以前にAPIを使用していたはずであることを意味します。 そうして初めて、GraphQLが自分にとってどれほど有益であるかを理解できるようになります。 GraphQLとApolloClientのいくつかの基本について説明しますが、JavaScriptとReactHooksに関する十分な知識が役立ちます。
GraphQLの基本
この記事はGraphQLの完全な紹介ではありませんが、続行する前にいくつかの規則を定義します。
GraphQLとは何ですか?
GraphQLは、クライアントが必要な正確なデータをAPIに要求するために使用できる宣言型クエリ言語を記述する仕様です。 これは、APIの強力な型スキーマを作成し、究極の柔軟性を実現することで実現されます。 また、APIがデータを解決し、クライアントクエリがスキーマに対して検証されることを保証します。 この定義は、GraphQLに、静的に型付けされた(Typescriptを中心に構築された)APIを備えた宣言型クエリ言語を作成するいくつかの仕様が含まれていることを意味し、クライアントがそれらの型システムを利用してAPIに必要な正確なデータを要求できるようにします。
したがって、いくつかのフィールドを含むいくつかのタイプを作成した場合、クライアント側から、「これらの正確なフィールドを含むこのデータを提供してください」と言うことができます。 次に、APIは、強く型付けされた言語で型システムを使用しているかのように、その正確な形状で応答します。 詳細については、私のTypescriptの記事をご覧ください。
続行するときに役立つGraphQlのいくつかの規則を見てみましょう。
基礎
- 操作
GraphQLでは、実行されるすべてのアクションは操作と呼ばれます。 いくつかの操作があります。つまり、次のとおりです。- クエリ
この操作は、サーバーからのデータのフェッチに関係しています。 読み取り専用フェッチと呼ぶこともできます。 - 突然変異
この操作には、サーバーからのデータの作成、更新、および削除が含まれます。 これは一般にCUD(作成、更新、および削除)操作と呼ばれます。 - サブスクリプション
GraphQLでのこの操作には、特定のイベントが発生したときにサーバーからクライアントにデータを送信することが含まれます。 これらは通常、WebSocketで実装されます。
- クエリ
この記事では、クエリとミューテーションの操作のみを扱います。
- 操作名
クライアント側のクエリおよびミューテーション操作には一意の名前があります。 - 変数と引数
操作は、ほとんどのプログラミング言語の関数と非常によく似た引数を定義できます。 これらの変数は、引数として操作内のクエリまたはミューテーション呼び出しに渡すことができます。 変数は、クライアントからの操作の実行中に実行時に指定されることが期待されます。 - エイリアシング
これは、クライアント側のGraphQLの規則であり、UIの単純で読みやすいフィールド名を使用して、冗長またはあいまいなフィールド名の名前を変更します。 競合するフィールド名を使用したくないユースケースでは、エイリアシングが必要です。
クライアントサイドGraphQLとは何ですか?
フロントエンドエンジニアがVue.jsや(この場合は)Reactなどのフレームワークを使用してUIコンポーネントを構築する場合、これらのコンポーネントは、サーバーからフェッチされるデータに合わせて、クライアント上の特定のパターンからモデル化および設計されます。
RESTful APIの最も一般的な問題の1つは、オーバーフェッチとアンダーフェッチです。 これは、クライアントがデータをダウンロードする唯一の方法が、固定データ構造を返すエンドポイントをヒットすることであるために発生します。 このコンテキストでのオーバーフェッチは、クライアントがアプリで必要とされるよりも多くの情報をダウンロードすることを意味します。
一方、GraphQLでは、必要なデータを含む単一のクエリをGraphQLサーバーに送信するだけです。 サーバーは、要求した正確なデータのJSONオブジェクトで応答するため、オーバーフェッチは発生しません。 Sebastian Eschweilerが、RESTfulAPIとGraphQLの違いについて説明しています。
クライアント側のGraphQLは、GraphQLサーバーからのデータとインターフェイスして、次の機能を実行するクライアント側のインフラストラクチャです。
- HTTPリクエストをすべて自分で作成しなくても、クエリを送信してデータを変更することでデータを管理します。 データの配管に費やす時間を減らし、実際のアプリケーションの構築により多くの時間を費やすことができます。
- キャッシュの複雑さを管理します。 そのため、サードパーティの干渉なしにサーバーからフェッチされたデータを保存および取得でき、重複するリソースの再フェッチを簡単に回避できます。 したがって、2つのリソースが同じである場合を識別します。これは、複雑なアプリに最適です。
- UIをOptimisticUIと一貫性のある状態に保ちます。これは、ミューテーションの結果(つまり、作成されたデータ)をシミュレートし、サーバーから応答を受信する前でもUIを更新する規則です。 サーバーから応答を受信すると、楽観的な結果は破棄され、実際の結果に置き換えられます。
クライアント側のGraphQLの詳細については、GraphQLの共同作成者やGraphQLRadioの他のクールな人々と1時間を割いてください。
Apolloクライアントとは何ですか?
Apollo Clientは、JavaScriptおよびネイティブプラットフォーム向けの相互運用可能で、非常に柔軟な、コミュニティ主導のGraphQLクライアントです。 その印象的な機能には、堅牢な状態管理ツール(Apollo Link)、ゼロ構成キャッシングシステム、データをフェッチするための宣言型アプローチ、実装が容易なページ付け、クライアント側アプリケーションのOptimisticUIが含まれます。
Apollo Clientは、サーバーからフェッチされたデータの状態だけでなく、クライアントでローカルに作成した状態も保存します。 したがって、APIデータとローカルデータの両方の状態を管理します。
また、競合することなく、Reduxなどの他の状態管理ツールと一緒にApolloClientを使用できることに注意することも重要です。 さらに、状態管理を、たとえばReduxからApollo Clientに移行することもできます(これはこの記事の範囲を超えています)。 最終的に、Apollo Clientの主な目的は、エンジニアがAPIでデータをシームレスにクエリできるようにすることです。
Apolloクライアントの機能
Apollo Clientは、最新の堅牢なアプリケーションを簡単に構築できる非常に便利な機能により、非常に多くのエンジニアや企業を獲得してきました。 次の機能が組み込まれています。
- キャッシング
Apollo Clientは、オンザフライでのキャッシュをサポートします。 - 楽観的なUI
Apollo Clientは、OptimisticUIをクールにサポートしています。 これは、操作の進行中に操作の最終状態(ミューテーション)を一時的に表示することを含みます。 操作が完了すると、実際のデータが楽観的なデータに置き換わります。 - ページ付け
Apollo Clientには、アプリケーションにページ付けを非常に簡単に実装できる機能が組み込まれています。useQuery
フックに付属するfetchMore
関数を使用して、パッチで、または一度にデータのリストをフェッチする際の技術的な問題のほとんどを処理します。
この記事では、これらの機能の一部を見ていきます。
十分な理論。 手を汚すので、シートベルトを締めて、パンケーキと一緒にコーヒーを飲みましょう。
Webアプリの構築
このプロジェクトはスコットモスに触発されています。
シンプルなペットショップのウェブアプリを作成します。その機能は次のとおりです。
- サーバー側からペットを取得します。
- ペットの作成(名前、ペットの種類、画像の作成を含みます);
- 楽観的なUIを使用する。
- ページ付けを使用してデータをセグメント化します。
まず、リポジトリのクローンを作成し、 starter
ブランチがクローンしたものであることを確認します。
入門
- Chrome用のApolloClient DeveloperTools拡張機能をインストールします。
- コマンドラインインターフェイス(CLI)を使用して、複製されたリポジトリのディレクトリに移動し、コマンドを実行してすべての依存関係を取得します:
npm install
。 - コマンド
npm run app
して、アプリを起動します。 - ルートフォルダにいる間に、コマンド
npm run server
。 これにより、バックエンドサーバーが起動し、続行するときに使用します。
アプリは設定されたポートで開く必要があります。 私のはhttps://localhost:1234/
です; あなたのものはおそらく別のものです。
すべてがうまく機能した場合、アプリは次のようになります。
表示するペットがいないことに気付くでしょう。 これは、そのような機能をまだ作成していないためです。
Apollo Client Developer Toolsを正しくインストールした場合は、開発者ツールを開いてトレイアイコンをクリックします。 「Apollo」と次のようなものが表示されます。
ReduxおよびReact開発者ツールと同様に、Apolloクライアント開発ツールを使用してクエリとミューテーションを記述およびテストします。 拡張機能には、GraphQLPlaygroundが付属しています。
ペットをフェッチする
ペットをフェッチする機能を追加しましょう。 client/src/client.js
に移動します。 Apolloクライアントを作成し、それをAPIにリンクし、デフォルトクライアントとしてエクスポートし、新しいクエリを作成します。
次のコードをコピーして、 client.js
に貼り付けます。
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http' const link = new HttpLink({ uri: 'https://localhost:4000/' }) const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
上記で起こっていることの説明は次のとおりです。
-
ApolloClient
これは、アプリをラップし、HTTPとのインターフェースを取り、データをキャッシュし、UIを更新する関数になります。 -
InMemoryCache
これは、アプリケーションのキャッシュの操作に役立つApolloClientの正規化されたデータストアです。 -
HttpLink
これは、GraphQLリクエストの制御フローを変更し、GraphQLの結果をフェッチするための標準のネットワークインターフェースです。 これはミドルウェアとして機能し、リンクが起動されるたびにGraphQLサーバーから結果をフェッチします。 さらに、Axios
やwindow.fetch
などの他のオプションの代わりにもなります。 -
HttpLink
のインスタンスに割り当てられるリンク変数を宣言します。 これは、uri
プロパティとサーバーへの値(https://localhost:4000/
)を取ります。 - 次は、
InMemoryCache
の新しいインスタンスを保持するキャッシュ変数です。 - クライアント変数も
ApolloClient
のインスタンスを取り、link
とcache
をラップします。 - 最後に、
client
をエクスポートして、アプリケーション全体で使用できるようにします。
これが実際に動作することを確認する前に、アプリ全体がApolloに公開されていること、アプリがサーバーからフェッチされたデータを受信できること、およびそのデータを変更できることを確認する必要があります。
これを実現するには、 client/src/index.js
にアクセスしてみましょう。
import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter } from 'react-router-dom' import { ApolloProvider } from '@apollo/react-hooks' import App from './components/App' import client from './client' import './index.css' const Root = () => ( <BrowserRouter>
<ApolloProvider client={client}> <App /> </ApolloProvider>
</BrowserRouter> ); ReactDOM.render(<Root />, document.getElementById('app')) if (module.hot) { module.hot.accept() }
強調表示されたコードでわかるように、 App
コンポーネントをApolloProvider
でラップし、クライアントを小道具としてclient
に渡しました。 ApolloProvider
は、ReactのContext.Provider
に似ています。 Reactアプリをラップし、クライアントをコンテキストに配置します。これにより、コンポーネントツリーのどこからでもクライアントにアクセスできます。
サーバーからペットをフェッチするには、必要なフィールドを正確に要求するクエリを作成する必要があります。 client/src/pages/Pets.js
に移動し、次のコードをコピーして貼り付けます。
import React, {useState} from 'react' import gql from 'graphql-tag' import { useQuery, useMutation } from '@apollo/react-hooks' import PetsList from '../components/PetsList' import NewPetModal from '../components/NewPetModal' import Loader from '../components/Loader'
const GET_PETS = gql` query getPets { pets { id name type img } } `;
export default function Pets () { const [modal, setModal] = useState(false)
const { loading, error, data } = useQuery(GET_PETS); if (loading) return <Loader />; if (error) return <p>An error occured!</p>;
const onSubmit = input => { setModal(false) } if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section>
<PetsList pets={data.pets}/>
</section> </div> ) }
数ビットのコードで、サーバーからペットをフェッチすることができます。
gqlとは何ですか?
GraphQLの操作は、通常、 graphql-tag
とバッククォートで記述されたJSONオブジェクトであることに注意してください。
gql
タグは、GraphQLクエリ文字列をGraphQL AST(抽象構文木)に解析するJavaScriptテンプレートリテラルタグです。
- クエリ操作
サーバーからペットを取得するには、クエリ操作を実行する必要があります。-
query
操作を行っているため、名前を付ける前に操作のtype
を指定する必要がありました。 - クエリの名前は
GET_PETS
です。 フィールド名にキャメルケースを使用するのはGraphQLの命名規則です。 - 私たちのフィールドの名前は
pets
です。 したがって、サーバーから必要な正確なフィールド(id, name, type, img)
を指定します。 -
useQuery
は、Apolloアプリケーションでクエリを実行するための基礎となるReactフックです。 Reactコンポーネントでクエリ操作を実行するために、useQuery
フックを呼び出します。これは、最初は@apollo/react-hooks
からインポートされました。 次に、GraphQLクエリ文字列(この場合はGET_PETS
)を渡します。
-
- コンポーネントがレンダリングされると、
useQuery
は、読み込み、エラー、およびデータのプロパティを含むオブジェクト応答をApolloクライアントから返します。 したがって、それらは構造化されていないため、UIをレンダリングするために使用できます。 -
useQuery
は素晴らしいです。async-await
を含める必要はありません。 それはすでにバックグラウンドで処理されています。 かなりかっこいいですね。-
loading
このプロパティは、アプリケーションの読み込み状態を処理するのに役立ちます。 この例では、アプリケーションのロード中にLoader
コンポーネントを返します。 デフォルトでは、ロードはfalse
です。 -
error
念のため、このプロパティを使用して、発生する可能性のあるエラーを処理します。 -
data
これには、サーバーからの実際のデータが含まれています。 - 最後に、
PetsList
コンポーネントで、data.pets
をオブジェクト値としてpets
を渡します。
-
この時点で、サーバーへのクエリは正常に完了しています。
アプリケーションを起動するには、次のコマンドを実行してみましょう。
- クライアントアプリを起動します。 CLIでコマンド
npm run app
します。 - サーバーを起動します。 別のCLIでコマンド
npm run server
します。
すべてがうまくいけば、次のように表示されます。
データの変更
Apollo Clientでのデータの変更またはデータの作成は、データのクエリとほとんど同じですが、わずかな変更があります。
まだclient/src/pages/Pets.js
にあり、強調表示されたコードをコピーして貼り付けましょう。
.... const GET_PETS = gql` query getPets { pets { id name type img } } `;
const NEW_PETS = gql` mutation CreateAPet($newPet: NewPetInput!) { addPet(input: $newPet) { id name type img } } `;
const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS);
const onSubmit = input => { setModal(false)
createPet({ variables: { newPet: input } }); } if (loading || newPet.loading) return <Loader />; if (error || newPet.error) return <p>An error occured</p>;
if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section> <PetsList pets={data.pets}/> </section> </div> ) } export default Pets
ミューテーションを作成するには、次の手順を実行します。
1. mutation
作成、更新、または削除するには、 mutation
操作を実行する必要があります。 mutation
テーション操作には、1つの引数を持つCreateAPet
名があります。 この引数には、 NewPetInput
タイプの$newPet
変数があります。 !
操作が必要であることを意味します。 したがって、タイプがNewPetInput
であるnewPet
変数を渡さない限り、GraphQLは操作を実行しません。
2. addPet
ミューmutation
操作内にあるaddPet
関数は、 input
の引数を取り、 $newPet
変数に設定されます。 addPet
関数で指定されたフィールドセットは、クエリのフィールドセットと同じである必要があります。 オペレーションのフィールドセットは次のとおりです。
-
id
-
name
-
type
-
img
useMutation
useMutation
Reactフックは、Apolloアプリケーションでミューテーションを実行するための主要なAPIです。 データを変更する必要がある場合は、ReactコンポーネントでuseMutation
を呼び出し、GraphQL文字列(この場合はNEW_PETS
)を渡します。
コンポーネントがuseMutation
をレンダリングすると、次のような配列でタプル(つまり、レコードを構成するデータの順序付けられたセット)が返されます。
- ミューテーションを実行するためにいつでも呼び出すことができる
mutate
関数。 - ミューテーションの実行の現在のステータスを表すフィールドを持つオブジェクト。
useMutation
フックには、GraphQLミューテーション文字列(この場合はNEW_PETS
)が渡されます。 タプルを非構造化しました。これは、データとオブジェクトフィールド( newPets
)を変更する関数( createPet
)です。
4. createPet
onSubmit
関数では、 setModal
状態の直後に、 createPet
を定義しました。 この関数は、値が{ newPet: input }
に設定されたオブジェクトプロパティを持つvariable
を取ります。 input
は、フォームのさまざまな入力フィールド(名前、タイプなど)を表します。
これが完了すると、結果は次のようになります。
GIFを注意深く観察すると、ページが更新された場合にのみ、作成されたペットがすぐに表示されないことがわかります。 ただし、サーバー上で更新されています。
大きな問題は、なぜ私たちのペットがすぐに更新されないのかということです。 次のセクションで調べてみましょう。
Apolloクライアントでのキャッシュ
アプリが自動的に更新されない理由は、新しく作成されたデータがApolloクライアントのキャッシュデータと一致しないためです。 そのため、キャッシュから正確に何を更新する必要があるかについては競合があります。
簡単に言えば、複数のエントリ(ノード)を更新または削除するミューテーションを実行する場合、そのノードを参照するクエリを更新する責任があります。これにより、キャッシュされたデータが、ミューテーションがバックに対して行う変更と一致するように変更されます。終了データ。
キャッシュの同期を維持する
ミューテーション操作を実行するたびにキャッシュの同期を維持する方法はいくつかあります。
1つは、 refetchQueries
オブジェクトプロパティを使用して、ミューテーション後に一致するクエリを再フェッチすることです(最も簡単な方法)。
注:このメソッドを使用する場合、 refetchQueries
というcreatePet
関数のオブジェクトプロパティを取得し、クエリの値を持つオブジェクトの配列を含みます: refetchQueries: [{ query: GET_PETS }]
。
このセクションでは、UIで作成したペットを更新するだけでなく、キャッシュを操作することに重点を置いているため、このメソッドは使用しません。
2番目のアプローチは、 update
機能を使用することです。 Apollo Clientには、キャッシュデータの変更を支援するupdate
ヘルパー関数があり、ミューテーションがバックエンドデータに加える変更と同期します。 この関数を使用して、キャッシュの読み取りと書き込みを行うことができます。
キャッシュの更新
次の強調表示されたコードをコピーして、 client/src/pages/Pets.js
に貼り付けます。
...... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } );
.....
update
関数は2つの引数を受け取ります。
- 最初の引数は、Apolloクライアントからのキャッシュです。
- 2つ目は、サーバーからの正確なミューテーション応答です。
data
プロパティを分解し、ミューテーション(addPet
)に設定します。
次に、関数を更新するには、更新する必要のあるクエリ(この場合はGET_PETS
クエリ)を確認し、キャッシュを読み取る必要があります。
次に、読み取ったquery
に書き込む必要があります。これにより、クエリを更新しようとしていることがわかります。 これを行うには、 query
data
プロパティを含み、値がquery
操作( GET_PETS
)に設定されているオブジェクトと、値がpet
オブジェクトであり、 addPet
ミューテーションの配列とペットのデータ。
これらの手順を注意深く実行すると、ペットを作成するときにペットが自動的に更新されるのを確認できます。 変更点を見てみましょう。
楽観的なUI
多くの人がローダーやスピナーの大ファンです。 ローダーを使用しても問題はありません。 ローダーが最良のオプションである完璧なユースケースがあります。 ローダーとスピナー、およびそれらの最良の使用例について説明しました。
ローダーとスピナーは確かにUIとUXの設計において重要な役割を果たしますが、OptimisticUIの登場は脚光を浴びています。
オプティミスティックUIとは何ですか?
オプティミスティックUIは、ミューテーション(作成されたデータ)の結果をシミュレートし、サーバーからの応答を受信する前にUIを更新する規則です。 サーバーから応答を受信すると、楽観的な結果は破棄され、実際の結果に置き換えられます。
結局のところ、楽観的なUIは、知覚されるパフォーマンスを管理し、状態の読み込みを回避する方法にすぎません。
Apollo Clientには、オプティミスティックUIを統合する非常に興味深い方法があります。 これにより、ミューテーション後にローカルキャッシュに書き込むことができる単純なフックが得られます。 それがどのように機能するか見てみましょう!
ステップ1
client/src/client.js
に移動し、強調表示されたコードのみを追加します。
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context' import { ApolloLink } from 'apollo-link' const http = new HttpLink({ uri: "https://localhost:4000/" }); const delay = setContext( request => new Promise((success, fail) => { setTimeout(() => { success() }, 800) }) ) const link = ApolloLink.from([ delay, http ])
const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
最初のステップは次のとおりです。
-
setContext
をapollo-link-context
からインポートします。setContext
関数はコールバック関数を受け取り、突然変異操作が実行されるときに遅延を作成するために、setTimeout
が800ms
に設定されているpromiseを返します。 -
ApolloLink.from
メソッドは、HTTP
からのリンク(API)を表すネットワークアクティビティが遅延することを保証します。
ステップ2
次のステップは、OptimisticUIフックを使用することです。 client/src/pages/Pets.js
に戻り、強調表示されたコードのみを以下に追加します。
..... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS); const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } ); const onSubmit = input => { setModal(false) createPet({ variables: { newPet: input },
optimisticResponse: { __typename: 'Mutation', addPet: { __typename: 'Pet', id: Math.floor(Math.random() * 10000 + ''), name: input.name, type: input.type, img: 'https://via.placeholder.com/200' } }
}); } .....
optimisticResponse
オブジェクトは、サーバーの応答を待つのではなく、ペットを作成したときにUIをすぐに更新する場合に使用されます。
上記のコードスニペットには、次のものが含まれます。
-
__typename
は、クエリされたエンティティのtype
をフェッチするためにApolloによってクエリに挿入されます。 これらのタイプは、apollo-cache
でキャッシュする目的でid
プロパティ(シンボル)を構築するためにApolloクライアントによって使用されます。 したがって、__typename
はクエリ応答の有効なプロパティです。 - ミューテーションは、
optimisticResponse
の__typename
として設定されます。 - 前に定義したように、ミューテーションの名前は
addPet
で、__typename
はPet
です。 - 次に、楽観的な応答を更新する必要があるミューテーションのフィールドを示します。
-
id
サーバーからのIDがわからないため、Math.floor
を使用してIDを作成しました。 -
name
この値はinput.name
に設定されます。 -
type
タイプの値はinput.type
です。 -
img
これで、サーバーが画像を生成するため、プレースホルダーを使用してサーバーからの画像を模倣しました。
-
これは確かに長い道のりでした。 最後まで来たら、コーヒーを飲みながら椅子から休憩することを躊躇しないでください。
結果を見てみましょう。 このプロジェクトのサポートリポジトリはGitHubにあります。 クローンを作成して試してみてください。
結論
Optimistic UIやページ付けなどのApolloClientの驚くべき機能により、クライアント側のアプリの構築が現実のものになります。
ApolloクライアントはVue.jsやAngularなどの他のフレームワークと非常にうまく機能しますが、React開発者はApolloクライアントフックを持っているため、優れたアプリの構築を楽しむしかありません。
この記事では、表面を引っかいただけです。 Apollo Clientをマスターするには、絶え間ない練習が必要です。 したがって、先に進んでリポジトリのクローンを作成し、ページ付けを追加して、リポジトリが提供する他の機能を試してみてください。
以下のコメントセクションでフィードバックと経験を共有してください。 Twitterで進捗状況について話し合うこともできます。 乾杯!
参考文献
- 「Client-SideGraphQLIn React」、Scott Moss、フロントエンドマスター
- 「ドキュメント」、Apolloクライアント
- 「Reactを使用した楽観的なUI」、Patryk Andrzejewski
- 「楽観的なユーザーインターフェイスの真の嘘」、Smashing Magazine