💡
laravel starter kit(react)でのtoastify (sonnar)
基本的にはshadcn/uiを使うのがよさそう
React-Toastify
もありますが、、、shadcn/ui
のtoastを見てみると
npx shadcn@latest add toast
Need to install the following packages:
shadcn@2.4.0-canary.12
Ok to proceed? (y)
The toast component is deprecated. Use the sonner component instead.
となる。
sonnerを使う
そういうわけで今はsonner
を使うようだ
npx shadcn@latest add sonner
✔ Checking registry.
Installing dependencies.
It looks like you are using React 19.
Some packages may fail to install due to peer dependency issues in npm (see https://ui.shadcn.com/react-19).
✔ How would you like to proceed? › Use --force
✔ Installing dependencies.
✔ Created 1 file:
- resources/js/components/ui/sonner.tsx
package.json
"laravel-react-i18n": "^2.0.5",
"laravel-vite-plugin": "^1.0",
"lucide-react": "^0.475.0",
+ "next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "sonner": "^2.0.1",
"tailwind-merge": "^3.0.1",
"tailwindcss": "^4.0.0",
"tailwindcss-animate": "^1.0.7",
このようにdependencyも解消される
ログイン完了時にflashメッセージを仕込む
構造はいろいろ議論の余地を残すが今回はこういう風にしよう
app/Http/Controllers/Auth/AuthenticatedSessionController.php
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(route('dashboard', absolute: false))
->with('flashMessage', ['success' => __('You are now logged in.')]);
}
flashMessage
というキーで仕込んでいる。
組み込み
back
app/Http/Middleware/HandleInertiaRequests.php
@@ -45,6 +45,7 @@ public function share(Request $request): array
'auth' => [
'user' => $request->user(),
],
+ 'flashMessage' => session()->get('flashMessage', []),
];
}
}
front
一般的にはlayoutにつっこんだ方がよいと思われる。resources/js/layouts/app-layout.tsx に存在する auth-layout.tsxも存在するけどこれはまあ必要ないんじゃないかな。
resources/js/layouts/app-layout.tsx
@@ -1,14 +1,29 @@
+import { Toaster } from '@/components/ui/sonner';
import AppLayoutTemplate from '@/layouts/app/app-sidebar-layout';
import { type BreadcrumbItem } from '@/types';
-import { type ReactNode } from 'react';
+import { usePage } from '@inertiajs/react';
+import { useEffect, type ReactNode } from 'react';
+import { toast } from 'sonner';
interface AppLayoutProps {
children: ReactNode;
breadcrumbs?: BreadcrumbItem[];
}
-export default ({ children, breadcrumbs, ...props }: AppLayoutProps) => (
- <AppLayoutTemplate breadcrumbs={breadcrumbs} {...props}>
- {children}
- </AppLayoutTemplate>
-);
+export default function AppLayout({ children, breadcrumbs, ...props }: AppLayoutProps) {
+ const { flashMessage } = usePage().props;
+ useEffect(() => {
+ if (flashMessage) {
+ Object.entries(flashMessage).forEach(([type, message]) => {
+ toast[type as keyof typeof toast](message);
+ });
+ }
+ }, [flashMessage]);
+
+ return (
+ <AppLayoutTemplate breadcrumbs={breadcrumbs} {...props}>
+ {children}
+ <Toaster />
+ </AppLayoutTemplate>
+ );
+}
言語
まあ何となく
ja.json
+ "You are now logged in.": "ログインしました。",
カスタマイズ
description
やaction
も追加できるけどflashMessageの場合あんま必要とされる事がないかな...
Discussion