Inertia.js+Laravel+React…便利ですよね!でも、レールに乗り始めれば早いけど、最初とか途中で「あー、init時に変数渡したい」ってなった時に「…ファイルどれだっけ?」ってなります。
なので、メモです。
結果だけ書くと、
- routes/web.php
- Controller.php
- HandleInertiaRequests.php
- resources/views/app.blade.php
- resources/js/app.tsx
- resources/js/Pages/Default.tsx
Laravelの起点はrouting
何でもそうですよね。RoutingでInertia::render()してたらそこが起点です。
<?php Route::prefix('/admin')->get('/{operation?}/{target?}/{property?}', function (){ return Inertia::render('Default', [ 'config' => config('config_to_inertia'), 'roles' => Role::all(), ]);
Controllerもチェック
routingでContollerメソッド指定の場合、メソッドでreturn Inertia::render()している場合もあります。
<?php public function access(string $token): InertiaResponse { return Inertia::render('Default', [ 'config' => [ 'app_name' => config('config_to_inertia'), ], 'fooparam' => $foo_array ]);
Bladeファイルの指定
Reactでいうindex.htmlのようなReactの起点となるのは app/Http/Middleware/HandleInertiaRequests.phpのrouteViewメソッド で指定される。
<?php protected $rootView = 'app'; public function rootView(Request $request) { $routeName = $request->route()->getName(); if (strpos($routeName, 'admin.') === 0) { return 'admin'; } if (strpos($routeName, 'your.route.name') === 0) { return 'foo'; } return parent::rootView($request); }
この場合、デフォルトでは、appを返すので、resources/views/app.blade.phpが起点となるbladeになる。route名によってbladeを変更できる。
BladeからInertiaへのつなぎこみ
app.blade.phpのこの部分で行う。
@vite(['resources/js/app.tsx', "resources/js/Pages/{$page['component']}.tsx"])
基本的にInertiaはPageRouter。
配列の1つ目がInertiaをセットアップするtsxで、2つ目が最初に表示されるPageになる。Inertia::render()'Default', [だと、$page['component']はDefaultになる。
Inertiaのセットアップ
先ほどの配列の1つ目 resources/js/app.tsxを見ると
import '../css/app.scss'; import './bootstrap'; import { createInertiaApp } from '@inertiajs/react'; import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; import { createRoot } from 'react-dom/client'; const appName = import.meta.env.VITE_APP_NAME || 'Laravel'; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.tsx`, import.meta.glob('./Pages/**/*.tsx'), ), setup({ el, App, props }) { const root = createRoot(el); root.render(<App {...props} />); }, progress: { color: '#4B5563', }, });
となっている。肝心なのは、resolvePageComponentのところ。第一引数には最初のページが入る。これは、最初のInertia::render()'Default', [で決まって、${name}はDefaultになる。
第二引数は、どのページを読み込むかの指定。 import.meta.glob('./Pages/**/*.tsx')だと resources/js/Pages/配下の全てのtsxファイルが使える。ただし、ReactのRoutingはまた別途
<BrowserRouter>
<Routes>
<Route>
でやる必要がある。