
はじめに
Webアプリケーションにおいて、ユーザー体験(UX)は非常に重要な要素です。特にチャットやメッセージ機能では、ページのリロードが発生するとユーザーの操作が中断され、スムーズな会話体験が損なわれてしまいます。今回は、Laravel(バックエンド)とReact(フロントエンド)を使用して、ページをリロードせずにメッセージを送信できるSPA(Single Page Application)形式の実装方法について解説します。
従来の実装とSPA実装の違い
従来の実装(ページリロードあり)
従来の実装では、フォーム送信時に以下のような流れになります。
- ユーザーがメッセージを入力して送信ボタンをクリック
- フォームがサーバーにPOSTリクエストを送信
- サーバーがデータを処理し、新しいページをレンダリング
- ブラウザが完全に画面をリロード
- ユーザーは入力位置や画面の状態を失う
SPA実装(リロードなし)
SPA実装では、フォーム送信時に以下のような流れになります。
- ユーザーがメッセージを入力して送信ボタンをクリック
- JavaScriptがAPIリクエストをサーバーに送信
- サーバーがデータを処理し、JSONレスポンスを返す
- フロントエンドがレスポンスを受け取り、UIを更新
- ユーザーの操作が中断されない
実装方法
今回は、LaravelとReact(TypeScript)を使用したSPAメッセージ機能の実装方法を紹介します。
バックエンド(Laravel)の実装
まず、メッセージ送信を処理するコントローラーを修正します。従来のリダイレクト処理に加えて、JSONレスポンスを返すようにします。
public function store(Request $request, ConversationGroup $conversationGroup): JsonResponse|RedirectResponse
{
// バリデーション
$request->validate([
'message' => 'required|string|max:1000',
]);
// ユーザー権限チェック
if (!$conversationGroup->hasParticipant(Auth::id())) {
abort(403, 'Unauthorized action.');
}
// メッセージ作成
$message = new DirectMessage([
'sender_id' => Auth::id(),
'message' => $request->message,
]);
$conversationGroup->messages()->save($message);
$conversationGroup->touch(); // updated_atを更新
// Ajax リクエストの場合は JSON レスポンスを返す
if ($request->expectsJson() || $request->ajax()) {
return response()->json([
'success' => true,
'message' => $message->load('sender'),
]);
}
// 通常のフォーム送信の場合はリダイレクト
return redirect()->back();
}
このコントローラーのポイントは以下の通りです。
- JsonResponse|RedirectResponseで両方のレスポンスタイプをサポート
- リクエストタイプに応じて適切なレスポンスを返す
- APIリクエストの場合は送信者情報も含めて返す
フロントエンド(React/TypeScript)の実装
次に、React側でのメッセージ送信処理を実装します。
import { useState, useEffect, useRef } from "react";
import { useForm } from "@inertiajs/react";
import axios from "axios";
import DirectMessage, { DirectMessageType } from "@/Components/DirectMessage";
// コンポーネント内
export default function Show({
auth,
conversationGroup,
messages: initialMessages,
participants,
}) {
// メッセージの状態管理
const [messages, setMessages] = useState<DirectMessageType[]>(initialMessages);
const [sending, setSending] = useState(false);
const messagesContainerRef = useRef<HTMLDivElement>(null);
const { data, setData, errors, reset } = useForm({
message: "",
});
// メッセージ送信処理
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!data.message.trim() || sending) {
return;
}
setSending(true);
try {
// CSRFトークンの取得
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '';
// APIでメッセージを送信
const response = await axios.post(
route("messages.store", conversationGroup.id),
data,
{
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
}
}
);
// 成功したら新しいメッセージを追加
if (response.data && response.data.message) {
const newMessage: DirectMessageType = {
...response.data.message,
sender: auth.user
};
setMessages([...messages, newMessage]);
reset("message");
}
} catch (error) {
console.error('メッセージ送信エラー:', error);
} finally {
setSending(false);
}
};
// メッセージが追加されたらスクロール位置を最下部に移動
useEffect(() => {
if (messagesContainerRef.current) {
messagesContainerRef.current.scrollTop =
messagesContainerRef.current.scrollHeight;
}
}, [messages]);
// JSXの返却(省略)
}
フロントエンド実装のポイントは以下の通りです。
- 状態管理
- useStateでメッセージリストと送信中の状態を管理
- 初期データはpropsから取得
- 非同期処理
- async/awaitを使った非同期処理
- 送信中の状態管理(二重送信防止)
- エラーハンドリング
- UX向上
- 新しいメッセージ送信後に自動的に入力欄をリセット
- 新しいメッセージ追加時に自動スクロール
- 送信中の視覚的フィードバック
実装のメリット
このSPA実装には以下のようなメリットがあります。
- シームレスなユーザー体験
- ページがリロードされないため、会話のコンテキストが維持される
- スムーズな操作感でユーザーのフラストレーションが軽減
- レスポンシブな操作感
- 送信後すぐにUIが更新されるため、操作への即時フィードバックがある
- 読み込み中やエラー状態も視覚的に表現できる
- サーバー負荷の軽減
- 必要なデータのみを送受信するため、帯域幅の使用が最適化される
- 全ページを再読み込みする必要がないため、サーバーリソースの使用が効率化
- 拡張性
- この基本的なパターンを応用して、リアルタイム通知やタイピングインジケーターなどの機能を追加可能
注意点とさらなる改善点
- エラーハンドリング
- ネットワークエラーや認証エラーなど、様々なエラーケースに対応する必要がある
- ユーザーにわかりやすいエラーメッセージを表示する
- バリデーション
- フロントエンドでも入力値のバリデーションを行うことでUXを向上させられる
- リアルタイム通信
- WebSocketやPusherなどを活用して、真のリアルタイムチャットにアップグレードできる
- オフライン対応
- Service Workerを使用してオフライン時のメッセージ送信をキューに入れるなどの機能も可能
まとめ
今回は、LaravelとReactを使ったSPA形式のメッセージ送信機能の実装方法を紹介しました。ページをリロードせずにメッセージを送信することで、ユーザー体験が大幅に向上します。この実装パターンは、チャット機能だけでなく、コメント機能やフォーム送信など、様々な場面で応用可能です。ユーザー体験を重視したウェブアプリケーション開発の参考にしていただければ幸いです。最後に、SPAのアプローチはモダンなWeb開発における標準的な手法になりつつあります。ユーザーの期待も高まる中、このような実装を取り入れることは、現代のWebアプリケーション開発において非常に重要なスキルとなっています。