tohokuaikiのチラシの裏

技術的ネタとか。

Inertia.js+ReactのAjaxって、Reactコンポーネントを返すんだ…

Laravel+Inertia.js+Reactの構成で作ってくれたScaffoldをそのまま使おうとしたけど、どうも import { useForm } from '@inertiajs/react'; の useFormで作った const { get, post, patch, delete } = useForm({ name: user.name, email: user.email }); の get/post/patch/deleteについては、こういう流れになっているっぽい。

  1. React側でAjaxを送る。
  2. Laravelでは、Contorllerで return Inertia::render('Profile', ['user' => $request->user()]); を返す。
  3. Inertia.jsはReactにProfileコンポーネントと、そのpropsとしてuserを描画しようとする。
  4. Inertia.jsはProfileコンポーネントresources/js/app.tsx で指定された resolvePageComponent の第一引数 ${name} をProfileに読み替えて探す。ただし探索範囲は、第二引数で指定されているファイル群に限られる。
  5. ReactはProfileコンポーネントを再描画する。再描画は、 resources/js/app.tsxsetup({ el, App, props }) { const root = createRoot(el); root.render(<App {...props} />); } 部分。

うーん、使えるかなー。

以下、ChatGPTに聞いてみた部分

質問

LaravelのInertia.jsでReactを使った場合、Inertia.jsが用意するAjax通信を行い、Laravel側のControllerで以下のResponseがあったとします。
Inertia::render('Profile/Edit', [user => $user])

この場合、
・Profile/EditはReactコンポーネントですか?
・Profile/Editコンポーネントは、既に読み込まれている必要がありますか?
・読み込まれているかどうかは、最初にアクセスしたページのBladeテンプレートにある、 @vite(['resources/js/admin.tsx' の admin.tsxの中で 以下にある resolvePageComponentで指定されたReactコンポーネントである必要がありますか?
createInertiaApp({
title: (title) => ${title} - ${appName},
resolve: (name) =>
resolvePageComponent(
./Pages/Admin/${name}.tsx,
import.meta.glob('./Pages/Admin/*/.tsx'),

Inertia.js を Laravel と React で使用する場合、上記のコードに関連する疑問に以下のようにお答えします。

1. Profile/Edit は React コンポーネントですか?

はい、Profile/Edit は React コンポーネントです。
Inertia.js の Inertia::render('Profile/Edit', [ 'user' => $user ]) は、フロントエンドで指定された名前(Profile/Edit)に対応するコンポーネントを解決してレンダリングします。

2. Profile/Edit コンポーネントは既に読み込まれている必要がありますか?

いいえ、事前にすべて読み込む必要はありません。
React コンポーネントは動的にインポートされるため、resolvePageComponent の設定に基づいて必要なコンポーネントのみ読み込まれます。例えば、import.meta.glob('./Pages/Admin/**/*.tsx') を使用してコンポーネントを動的に解決する仕組みがあるため、Profile/Edit が必要になったタイミングでロードされます。

3. Blade テンプレートにある @vite([...])resolvePageComponent の設定に依存しますか?

はい、依存します。
以下の点を確認してください:

  1. Blade テンプレートで正しく Vite を読み込む:
    @vite(['resources/js/admin.tsx']) のような記述で、フロントエンドのエントリーポイント(例: admin.tsx)を正しく読み込む必要があります。

  2. resolvePageComponent の設定:
    resolvePageComponent 関数は、Profile/Edit という文字列がどのファイルに対応するかを決定します。例えば、以下のコード:

   resolvePageComponent(
       `./Pages/Admin/${name}.tsx`,
       import.meta.glob('./Pages/Admin/**/*.tsx')
   )

この設定では、Profile/Edit./Pages/Admin/Profile/Edit.tsx というパスに対応します。このパスで対応するコンポーネントが存在する必要があります。

重要なポイントまとめ:

  • Profile/Edit は Inertia.js のルート名に対応する React コンポーネント
  • 必要なコンポーネントは動的にインポートされるので、事前に全て読み込む必要はない。
  • resolvePageComponent と Vite の設定が正しく行われていることが重要です。

もし Profile/Edit が正しく解決されない場合、resolvePageComponent の設定やパスが間違っていないか確認してください。また、ブラウザのコンソールやネットワークタブでエラーを確認するのも役立ちます。