Laravel+React+Inertiaでフラッシュメッセージを表示する
はじめに
Laravelでフラッシュメッセージを表示する方法は簡単です。ただ、フロントエンドをReactで実装する場合は手順が異なります。今回はInertiaを使って簡単に実装する方法をメモしました。
環境:
- PHP: 8.2.x
- Laravel: 10.x
- React: 18.2.x
- Inertia : 1.0.12
Laravel+Bladeで実装する場合
Laravelでは以下のように、コントローラからwith
メソッドでセッションにフラッシュデータを保存し、Blade上でsession
メソッドを使って取得して表示するだけです。
// コントローラで渡す
return to_route('customers.index')
->with('message', '登録成功しました。');
// Bladeで表示する
@if (session('message'))
<div className="alert alert-success">
{{ session('message') }}
</div>
@endif
Reactの場合は上記のようなsession
メソッドは使えないため、どのようにデータの取得するか考える必要があります。その手順を次から説明していきます。
Laravel+Inertia+Reactでの実装手順
Inertiaを使って、各リクエストで自動的にセッションデータをpropsに渡すように設定します。
この方法はInertiaドキュメントのShared dataという項目で説明されています。今回のフラッシュメッセージに限らず、複数ページで表示したい共通データを毎回手動でpropsに渡す手間を省くことができます。
Laravelからセッションデータを渡す
Bladeを使う場合と同じで、コントローラからwith
メソッドでデータをセッションに保存します。
例えば、CustomerController
で登録処理完了後にメッセージと共にindex
ページへリダイレクトさせるとします。
// CustomerController.php
public function store(CustomerStoreRequest $request): RedirectResponse
{
Customer::create([
// 登録処理
]);
return to_route('customers.index')->with('message', '登録成功しました。');
}
セッションを共有データに設定
HandleInertiaRequests
ミドルウェアのshare
メソッドに、共有したいデータを連想配列の形で定義します。
// app/Http/Middleware/HandleInertiaRequests.php
class HandleInertiaRequests extends Middleware
{
public function share(Request $request)
{
return array_merge(parent::share($request), [
'flash' => [
'message' => fn () => $request->session()->get('message')
],
]);
}
}
ここでは、Laravelのセッションからmessage
というキーでフラッシュメッセージを取得してflash
キーに追加しています。フラッシュメッセージの種類が増えたらflash
配列に追加していきます。
Reactで共有データを取得
InertiaのusePage
フックを使うことで、ページに渡されたpropsを参照できます。今回flash
というデータを取り出す場合、以下のように分割代入で取り出します。
// resources/js/Pages/Customer/Index.jsx
import { usePage } from "@inertiajs/react";
const { flash } = usePage().props;
もしくは、以下のようにも書くことができます。
const flash = usePage().props.flash;
あとはflash.message
で値にアクセスして、メッセージが存在する時だけ以下のように表示します。
{flash.message && (
<div className="alert alert-success">{flash.message}</div>
)}
注意点
Shared dataを使用する際には以下の点に注意が必要です。
- 他のpropsと名前が競合しないように注意すること
- 全てのレスポンスに共有データが含まれるため、無駄に多くのデータを共有しないようにすること
参考ソース
- Inertia公式ドキュメント: Shared data - Inertia.js