クライアントアプリケーション統合
前の章では、GraphiQL エクスプローラーを使用して永続クエリを作成しおよび更新しました。
この章では、既存の React コンポーネント 内部で HTTP GET リクエストを使用して、永続クエリを WKND クライアントアプリケーション(WKND アプリ)に統合する手順について説明します。また、AEM ヘッドレスの習得事項つまりコーディング専門知識を適用して、WKND クライアントアプリケーションを強化するオプション課題も提供します。
前提条件 prerequisites
このドキュメントは、複数のパートで構成されているチュートリアルの一部です。 この章を進める前に、前の章が完了していることを確認してください。 WKND クライアントアプリケーションは AEM パブリッシュサービスに接続するので、次のものを AEM パブリッシュサービスに公開してある ことが重要です。
- プロジェクト設定
- GraphQL エンドポイント
- コンテンツフラグメントモデル
- 作成済みコンテンツフラグメント
- GraphQL 永続クエリ
この章の IDE スクリーンショットは、Visual Studio Code から取得したもの です。
第 1~4 章:ソリューションパッケージ(オプション) solution-package
第 1~4 章の AEM UI の手順を完了するソリューションパッケージをインストールできます。 前の章が完了している場合、このパッケージは 不要 です。
- Advanced-GraphQL-Tutorial-Solution-Package-1.2.zip をダウンロード します。
- AEM で、ツール/デプロイメント/パッケージ に移動して、 パッケージマネージャー にアクセスします。
- 前の手順でダウンロードしたパッケージ(zip ファイル)をアップロードしインストールします。
- パッケージを AEM パブリッシュサービスにレプリケートします。
目的 objectives
このチュートリアルでは、AEM Headless Client for JavaScript を使用して永続クエリのリクエストをサンプルの WKND GraphQL React アプリに統合する方法を説明します。
サンプルクライアントアプリケーションのクローン作成と実行 clone-client-app
チュートリアルの進行を促進するために、スターター React JS アプリが提供されます。
-
adobe/aem-guides-wknd-graphql リポジトリのクローンを作成します。
code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
-
aem-guides-wknd-graphql/advanced-tutorial/.env.development
ファイルを編集し、REACT_APP_HOST_URI
がターゲット AEM パブリッシュサービスを指すように設定します。オーサーインスタンスに接続する場合は、認証方法を更新します。
code language-plain # Server namespace REACT_APP_HOST_URI=https://publish-pxx-eyy.adobeaemcloud.com #AUTH (Choose one method) # Authentication methods: 'service-token', 'dev-token', 'basic' or leave blank to use no authentication REACT_APP_AUTH_METHOD= # For Bearer auth, use DEV token (dev-token) from Cloud console REACT_APP_DEV_TOKEN= # For Service toke auth, provide path to service token file (download file from Cloud console) REACT_APP_SERVICE_TOKEN=auth/service-token.json # For Basic auth, use AEM ['user','pass'] pair (eg for Local AEM Author instance) REACT_APP_BASIC_AUTH_USER= REACT_APP_BASIC_AUTH_PASS=
note note NOTE 上記の手順は、React アプリを AEM パブリッシュサービス に接続します。ただし、AEM オーサーサービス に接続するには、ターゲット AEM as a Cloud Service 環境のローカル開発トークンを取得します。 基本認証を使用して、アプリを AEMaaCS SDK を使用したローカルオーサーインスタンスに接続することもできます。 -
ターミナルを開き、次のコマンドを実行します。
code language-shell $ cd aem-guides-wknd-graphql/advanced-tutorial $ npm install $ npm start
-
新しいブラウザーウィンドウで http://localhost:3000 が読み込まれます。
-
Camping/Yosemite Backpacking をタップ して、Yosemite Backpacking アドベンチャーの詳細を確認します。
-
ブラウザーの開発者ツールを開き、
XHR
リクエストを調べますGraphQL エンドポイントへの
GET
リクエスト(プロジェクト設定名:wknd-shared
、永続クエリ名:adventure-by-slug
、変数名:slug
、値:yosemite-backpacking
および特殊文字エンコーディング)が表示されます。
http://localhost:3000
に対して行われた理由については、基本チュートリアルで内部の処理を確認してください。コードのレビュー
基本チュートリアル - AEM GraphQL API を使用した React アプリの作成ステップでは、主要なファイルをいくつか確認し拡張して実践的な専門知識を獲得しました。WKND アプリを強化する前に、主要なファイルを確認します。
Adventures
React コンポーネントのレビュー
WKND React アプリのメインビューは、すべての Adventure のリストです。これらの Adventure は、Camping や Cycling のようなアクティビティタイプに基づいてフィルタリングできます。このビューは、Adventures
コンポーネントによってレンダリングされます。主な実装の詳細を以下に示します。
-
src/components/Adventures.js
はuseAllAdventures(adventureActivity)
フックを呼び出します。ここではadventureActivity
引数がアクティビティタイプです。 -
useAllAdventures(adventureActivity)
フックは、src/api/usePersistedQueries.js
ファイルで定義されます。adventureActivity
値に基づいて、呼び出す永続クエリを決定します。null 値でない場合はwknd-shared/adventures-by-activity
を呼び出し、それ以外の場合は使用可能なすべてのadventurewknd-shared/adventures-all
を取得します。 -
フックは、クエリの実行を
aemHeadlessClient.js
経由でAEMHeadless
にデリゲートするメインのfetchPersistedQuery(..)
関数を使用します。 -
また、フックは AEM GraphQL レスポンスから
response.data?.adventureList?.items
にある関連データのみを返すので、Adventures
React の表示コンポーネントを親の JSON 構造に依存せずに済みます。 -
クエリが正常に実行されると、
Adventures.js
のAdventureListItem(..)
レンダリング関数が HTML 要素を追加して、画像、トリップの長さ、価格およびタイトル 情報を表示します。
AdventureDetail
React コンポーネントのレビュー
AdventureDetail
React コンポーネントは、adventure の詳細をレンダリングします。主な実装の詳細を以下に示します。
-
src/components/AdventureDetail.js
はuseAdventureBySlug(slug)
フックを呼び出します。ここではslug
引数がクエリパラメーターです。 -
上記のように、
useAdventureBySlug(slug)
フックは、src/api/usePersistedQueries.js
ファイルで定義されます。aemHeadlessClient.js
経由でAEMHeadless
にデリゲートして、wknd-shared/adventure-by-slug
永続クエリを呼び出します。 -
クエリが正常に実行されると、
AdventureDetail.js
のAdventureDetailRender(..)
レンダリング関数が HTML 要素を追加して、adventure の詳細を表示します。
コードの機能強化
adventure-details-by-slug
永続クエリの使用
前の章では、adventure-details-by-slug
永続クエリを作成しました。これは、場所、instructorTeam および管理者 などの追加のアドベンチャー情報を提供します。adventure-by-slug
を adventure-details-by-slug
永続クエリに置換して、この追加情報をレンダリングしましょう。
-
src/api/usePersistedQueries.js
を開きます。 -
関数
useAdventureBySlug()
を見つけて、クエリを次のように更新します
...
// Call the AEM GraphQL persisted query named "wknd-shared/adventure-details-by-slug" with parameters
response = await fetchPersistedQuery(
"wknd-shared/adventure-details-by-slug",
queryParameters
);
...
追加情報の表示
-
追加のアドベンチャー情報を表示するには、
src/components/AdventureDetail.js
を開きます -
関数
AdventureDetailRender(..)
を見つけて、戻り関数を次のように更新しますcode language-javascript ... return (<> <h1 className="adventure-detail-title">{title}</h1> <div className="adventure-detail-info"> <LocationInfo {...location} /> ... <Location {...location} /> <Administrator {...administrator} /> <InstructorTeam {...instructorTeam} /> </div> </>); ...
-
対応するレンダリング関数も定義します。
LocationInfo
code language-javascript function LocationInfo({name}) { if (!name) { return null; } return ( <> <div className="adventure-detail-info-label">Location</div> <div className="adventure-detail-info-description">{name}</div> </> ); }
場所
code language-javascript function Location({ contactInfo }) { if (!contactInfo) { return null; } return ( <> <div className='adventure-detail-location'> <h2>Where we meet</h2> <hr /> <div className="adventure-detail-addtional-info">Phone:{contactInfo.phone}</div> <div className="adventure-detail-addtional-info">Email:{contactInfo.email}</div> </div> </>); }
InstructorTeam
code language-javascript function InstructorTeam({ _metadata }) { if (!_metadata) { return null; } return ( <> <div className='adventure-detail-team'> <h2>Instruction Team</h2> <hr /> <div className="adventure-detail-addtional-info">Team Name: {_metadata.stringMetadata[0].value}</div> </div> </>); }
管理者
code language-javascript function Administrator({ fullName, contactInfo }) { if (!fullName || !contactInfo) { return null; } return ( <> <div className='adventure-detail-administrator'> <h2>Administrator</h2> <hr /> <div className="adventure-detail-addtional-info">Name: {fullName}</div> <div className="adventure-detail-addtional-info">Phone: {contactInfo.phone}</div> <div className="adventure-detail-addtional-info">Email: {contactInfo.email}</div> </div> </>); }
新しいスタイルの定義
-
src/components/AdventureDetail.scss
を開き、次のクラス定義を追加しますcode language-css .adventure-detail-administrator, .adventure-detail-team, .adventure-detail-location { margin-top: 1em; width: 100%; float: right; } .adventure-detail-addtional-info { padding: 10px 0px 5px 0px; text-transform: uppercase; }
上記の機能強化を完了すると、WKND アプリは以下のようになり、ブラウザーのデベロッパーツールは adventure-details-by-slug
永続クエリ呼び出しを示します。
機能強化の課題(オプション)
WKND React アプリのメインビューでは、Camping や Cycling などのアクティビティタイプに基づいて、これらの Adventure をフィルタリングできます。ただし、WKND ビジネスチームは、場所 ベースのフィルタリング機能を追加したいと考えています。使用するための要件は以下のとおりです。
- WKND アプリのメインビューで、左上隅または右上隅に「場所」フィルタリングアイコンを追加します。
- 「場所」フィルタリングアイコンをクリックすると、場所のリストが表示されます。
- リストから目的の場所のオプションをクリックすると、一致する Adventure のみが表示されます。
- 一致するアドベンチャーが 1 つしかない場合は、Adventure Detail ビューが表示されます。
これで完了です
おめでとうございます。これで、永続クエリのサンプル WKND アプリへの統合と実装が完了しました。