ルーティング
ユーザーがストアフロントドメインでリクエストを行うと、pwa-kit-react-sdk/ssr/server/react-rendering
で定義されている render
という Express.js ハンドラーによって処理されます。ハンドラーはレスポンスとしてレンダリングするコンポーネントを選択します。このタイプのコンポーネントはルートと呼ばれます。レンダリングで使用可能なルートは、app/routes.jsx
の routes
と呼ばれるオブジェクト配列で定義されています。
ルート配列は、React Router で定義されているように、ルート構成の形状に従います。routes
配列の各オブジェクトは、以下のプロパティをもつことができます:
キー | タイプ | 説明 | 参照ドキュメント |
---|---|---|---|
path | Express-style 文字列、文字列の配列、または正規表現 | 受信リクエストパスと一致するかどうかが比較されるパス | React Router API → Route コンポーネント → path |
component | 関数 (routes.jsx にインポート) | パスがリクエストと一致する場合にレンダリングするコンポーネント | React Router API → Route コンポーネント → component |
exact | ブール値 | パスが完全一致でなければならないかどうかを決定します | React Router API → Route コンポーネント → exact |
新しく生成されたプロジェクトでは、ホーム、PLP、PDP などの多くの標準的な eコマースページのオブジェクトが routes
配列にすでに含まれています。
では、React アプリは、任意のリクエストに対してレンダリングするための適切なコンポーネントをどのようにして選択するのでしょうか。この場合、React Router ライブラリを使用して、リクエストされたパスと一致する path
文字列が見つかるまで、routes
配列のルート構成オブジェクトが順番に検索されます。
React Router には path
文字列の作成のために多くのオプションが用意されています。同じコンポーネントに対して複数のパスを指定し、正規表現を使用してパターンに従うパスを一致できます。
React Router は、Retail React App 全体でナビゲーションを実装するためにも使用されます。たとえば、すべてのハイパーリンクは React Router の Link
コンポーネントを使用します。React Router には、ブラウザーの履歴やクエリパラメーターなどにアクセスできるその他のコンポーネントが用意さています。
React Router の使用に関する詳細は、公式ドキュメントを参照してください。(バージョン 5 のドキュメントのみを参照してください。その他のバージョンでは異なるパターン一致システムが使用されています。)
routes
配列で指定されている各コンポーネントは、自動的に PWA Kit React SDK の高階コンポーネント、routeComponent
関数で強化されます。routeComponent
の作成に使用されるベースクラスによって、いくつかの静的メソッドが定義されます。これには、ストアフロントデベロッパーがカスタマイズ可能な 2 つの重要なメソッド、getProps
と shouldGetProps
が含まれます。
getProps
メソッドは、props
オブジェクトを経由して routeComponent
にデータを供給するために使用します。これらのデータは API リクエストからフェッチします。
routeComponent
は、routes
配列のコンポーネントを強化する際に、そのコンポーネントのプロパティの内部で getProps
という関数を探します。ここに関数を定義しておくと、強化されたコンポーネントのメソッドとして表示されます。routes
配列のすべてのコンポーネントに対して関数を定義する必要はありません。レンダリングの前にデータをフェッチするコンポーネントだけで構いません。
定義される getProps
関数は、promise を返します。promise が解決されると、コンポーネントがレンダリングされるときに、props
オブジェクトを経由して強化されたコンポーネントに、解決された値が渡されます。
routes
配列のコンポーネントがレンダリングされる場合は、コンポーネントの getProps
メソッドが 1 つの JavaScript オブジェクトとともに提供されます。このオブジェクトは、レンダリングのコンテキストに応じて以下のプロパティをもちます。
キー | タイプ | 説明 | 可用性 | その他 |
---|---|---|---|---|
params | オブジェクト | Express-style ルート文字列で指定されているルートパラメーターに対応するオブジェクトプロパティを含みます。たとえば、ルート /user/:name がある場合、リクエストパスの :name の値は params.name として使用できます。デフォルト値は {} 。 | クライアント側とサーバー側の両方 | Express API → Request → req.params |
req | オブジェクト | Express によって強化された Node のリクエストオブジェクトのバージョン。HTTP リクエストを表現し、クエリ文字列、パラメーター、ボディ、HTTP ヘッダーなどのプロパティをもちます。 | サーバー側のみ | Express API → Request |
res | オブジェクト | HTTP リクエストを受け取った際に Express アプリが送信する HTTP レスポンスを表現します。 | サーバー側のみ | Express API → Response |
location | 文字列 | リクエストの URL。 | クライアント側とサーバー側の両方 | Express API の一部ではありません。 |
- v3.0.0 では、
getProps
の代わりに使用できるwithReactQuery
と呼ばれる新しいデータ取得戦略が導入されました。 withReactQuery
とwithLegacyGetProps
は両方同時に使用できます。getProps
とshouldGetProps
は Retail React App ページのデフォルトテンプレートから削除されましたが、廃止予定ではありません。これらのメソッドは引き続き長期的にサポートされます。
v3 へのアップグレードを参照してください。
getProps
関数のエラーを処理するには、2 つのオプションがあります。
最初のオプションは、pwa-kit-react-sdk/ssr/universal/errors
からインポートできる HTTPError
オブジェクトをスローすることです。HTTPError
をスローすると、専用の Error
コンポーネントがレンダリングされます。
2 番目のオプションは、props を使用して、レンダリングされるコンポーネントにエラーを知らせ、カスタムのエラー処理ロジックで使用できるようにすることです。
以下に、両方のエラー処理のアプローチを使用する例を示します:
getProps
で返されたオブジェクトは、シリアル化されて、ページソースの __PRELOADED_STATE__
という名前のオブジェクトを経由して、レンダリングされる HTML に埋め込まれます。
レンダリングされる HTML のサイズを小さく抑えるために、getProps
で返すデータは最小限にしてください。たとえば、可能であれば API リクエストからのレスポンス全体を返すことは避けるようにします。
サーバー側でレンダリングされるページのバージョンをブラウザーでプレビューするには、URL の最後に?__server_only
を追加します。このクエリパラメーターは ハイドレーション プロセスを停止するため、ブラウザーはレンダリングを行わず、サーバー側のレンダリング後にページが変更されません。__PRELOADED_STATE__
オブジェクトの pretty-print バージョンを表示するには、クエリ文字列に ?__server_only&__pretty_print
を追加します。
クライアント側のレンダリング中にユーザーが後続のページにナビゲートすると、そのページはすぐにレンダリングされます。レンダリングは getProps
によるデータのフェッチ中に行われる場合があるため、未定義の props を処理するための条件コードを常にコンポーネントに書き込みます。また、props が未定義の際には、プレースホルダーコンポーネントをレンダリングすることを覚えておいてください (Chakra UI の Skeleton と同様)。
クライアント側では、コンポーネントの render
メソッドは getProps
が解決する前と後に呼び出されます。コンポーネントに渡された isLoading
プロップを使用して、読み込み画面をレンダリングするかどうかを決定します。
getProps
で複数の HTTP リクエストを行う場合、並行して行うようにします。並行して行えない場合は、クライアント側レンダリングへの移行を検討します。
クライアント側でデータを取得するだけの場合、getProps
ではなく、コンポーネントで React フックを使用します。
すべてのルートで同じコードを実行したい場合は、特殊コンポーネントの 1 つである App
コンポーネントに属する getProps
関数を定義します。特殊コンポーネントは、複数のルートで共有される機能の追加に使用されます。App コンポーネントやその他の特殊コンポーネントについて詳しくは、特殊コンポーネントのガイドを参照してください。
shouldGetProps
メソッドを使用して、getProps
メソッドを呼び出すタイミングをコントロールします。サーバー側のレンダリング中は、shouldGetProps
は 1 回のみ呼び出されます。クライアント側のレンダリング中は、React のライフサイクルメソッドの componentDidUpdate
が呼び出されるたびに呼び出されます。
デフォルトでは、getProps
は location.pathname
の値が変更されるたびに getProps
を呼び出します。routes
配列内の各コンポーネントのデフォルトの動作は、shouldGetProps
と呼ばれる独自の関数をコンポーネントのプロパティとして定義することで上書きできます。shouldGetProps
をカスタマイズして、リクエストを検査し、特定のリクエストに対してのみ getProps
を呼び出すことができます。
ソースコードをレビューして、ルーティングについての理解を深めてください。以下にあげる Retail React App の主要なファイルを確認してください。
app/routes.jsx
: パスの一致 (指定されたルートパラメーターを含む) の Express-style 構文を示します。app/pages/product-detail/index.jsx
: PDP 用のこのサンプルコンポーネントには、getProps
とshouldGetProps
の両方のためのカスタム関数が含まれています。app/components/_app_config/index.jsx
: 広範囲の構成コードと、アプリ全体でのgetProps
関数が含まれています。
別のルーティング方法については、URL 解決をご覧ください。
PWA Kit ドキュメントを参照する際は、Retail React App のアーキテクチャガイドを必ずお読みください。