Astro に React をぶち込んでルーティングさせたアレ

note

アレがアレ。

Astro で構築しているサイトの一部ページにフォームを入れることになった。
送信処理は API を用意してもらえるため、フロントの処理を書くのだが、入力画面 -> 確認画面 -> 完了画面 のフローを取っていることもありデータ処理のしやすい React を使うことにした。

Astro がそもそも React を使えるようにできているため、特別なこともせずに導入まではいけたものの、一部を SPA として動作させるノウハウがなかったためどうしようか迷って、その結果 react-router-dom を入れることにした。
フォームの処理についても react-form-hook を使ってやることにした。面倒なバインディングは全部処理してくれるので大変助かる。
フォームの context をルータを挟んだ状態で共有できるのか不安だったが、以下の書き方で通った。変に永続化するステート管理とか入れたくないのでよかった。

<FormProvider {...methods}>
  <RouterProvider router={ router } />
</FormProvider>

時間がなかったので詳細を調べていないが、 createRoutesFromElements を使えば特定のルートでのみ共有できる context とか設定できるんだろうか。

Astro 側はルータを置いたコンポーネントを読んで置くだけなのでかなり簡単だった。一応、注意点として createBrowserRouter を使う場合は Astro での出力ができないので、読み込んだコンポーネントに client:only="react" を付与する必要がある。
404 や直接のアクセスへの対応として、 react-router-dom の方で設定した URI に対応するように pages にも適当にファイルを配置しておく。今回は SSR なので Astro 側の確認画面に Astro.redirect を書いて入力画面に遷移させることで対応した。React のルーティングはサーバへのリクエストを挟まないので Astro 側で処理することによって React での遷移では表示させて直接のアクセス等の React が絡まないアクセスについては弾いていることになっていると思う。思うけど不安になってきた。
SSG の場合については React 側でステート持たせて確認取るみたいなフローになると思う。

もう一点、Astro と React で同じ目的のコンポーネントを作成してしまうというアレをやらかした。
そもそもフォームが入ることは事前に決まっていたため、汎用コンポーネントについては React で構築すればよかったのだが、静的なページが先行していたため考えなしに Astro でコンポーネントを作成してしまった。
Astro -> React の一方通行なので汎用コンポーネントについては React で構築するか、全部 React で構築してしまった方が良いだろう。
React に限った話ではないし、今後もやらかしそうなのでちょっと注意したい。