Algoliaの`react-instantsearch-hooks`では、`InstantSearch`配下にSSG / SSRしたい要素を配置しない方がよさそう
Algoliaが提供しているreact-instantsearch-hooksを使う場合、InstantSearchコンポーネントの下にはSSRやSSGしたいコンテンツ(OGP / SEO系など)を配置するとうまく動かな […]
目次
Algoliaが提供しているreact-instantsearch-hooks
を使う場合、InstantSearch
コンポーネントの下にはSSRやSSGしたいコンテンツ(OGP / SEO系など)を配置するとうまく動かない様子です。
ちょっとハマったので覚書。
やってたこと
サイトのHeader部分に配置した検索フォームを、Instantsearchと連動させようとしました。
そのため、Next.jsのpages/_app.tsx
にInstantSearch
コンポーネントを配置し、サイト全体をInstantSearch hookが使える状態にしました。
起きたこと
ページごとに設定したOGPタグの情報が、FacebookやTwitterで認識されなくなりました。
たまたまInstantSearch
コンポーネントの外に配置していたmeta
タグがあり、それだけが認識されていたことから発覚しました。
考えられる原因
InstantSearch
のコードを見ると、少なくともv6.29.0では、「特定の条件でnullを返す」実装でした。
// https://github.com/algolia/react-instantsearch/blob/v6.29.0/packages/react-instantsearch-hooks/src/components/InstantSearch.tsx#L23-L25
const search = useInstantSearchApi<TUiState, TRouteState>(props);
if (!search.started) {
return null;
}
SSRやSSG実行時、この条件分岐によってnull
が返され、子要素(children
)に配置したものが全て処理されていなかった可能性があります。
うまく動かないマークアップ
状況をシンプルにまとめたものがこちらです。この場合、InstantSearch
がnull
を返すと、children
が無視されてタイトルが反映されなくなります。
<InstantSearch>
<Head>
<title>Site Title</title>
</Head>
</InstantSearch>
対応: 検索ページのみにInstantSearch
コンポーネントを配置
ひとまずの対応として、InstantSearch
コンポーネントをpages/_app.tsx
から除去しました。現在は、検索結果を表示するページ(pages/search.tsx
)に配置しています。
ヘッダーの検索フォームについては、URLのクエリストリングへ検索クエリを付与する形とし、検索結果ページに飛ぶ実装に変更しています。
もう一つの対応案: SSR
公式のサンプルでは、react-instantsearch-hooks-server
を使ったSSR対応も紹介されています。
こちらでも対応できる様子ですが、やはりHead
タグはInstantSearch
要素の外に配置する必要がありそうです。
<InstantSearchSSRProvider {...serverState}>
<Head>
<title>React InstantSearch Hooks - Next.js</title>
</Head>
<InstantSearch>
...
今回は「利用するページを限定するだけで済みそうだったこと」と「SSRではなくSSG・ISRを使いたかったこと」の2点から採用していません。
が、next-auth
などの認証系を組み込んだアプリのような、ページを静的化するつもりがない性質であれば十分に利用できると思います。