🥁
shadcn/uiでのトラブルシューティング(Toast編)
はじめに
- shadcn/ui で
Toast
を利用した際に、<Toaster>
の配置位置によってエラーが出るのでメモとして残します。
結論
<body>
の配下に <Toaster>
を配置すれば問題ありません。
...
<html lang="ja">
<body className="">
<main>{children}</main>
<Toaster />
</body>
</html>
...
<body>
の外に配置するとエラーが出ます。
...
<html lang="ja">
<body className="">
<main>{children}</main>
</body>
<Toaster />
</html>
...
念のため動作確認します。まずは正しい使い方を確認します。
Next.jsプロジェクトの新規作成
作業するプロジェクトを新規に作成していきます。
長いので、折りたたんでおきます。
新規プロジェクト作成と初期環境構築の手順詳細
$ pnpm create next-app@latest nextjs-shadcnui-toast-error-fix-sample --typescript --eslint --import-alias "@/*" --src-dir --use-pnpm --tailwind --app
$ cd nextjs-shadcnui-toast-error-fix-sample
以下の通り不要な設定を削除し、プロジェクトの初期環境を構築します。
$ mkdir src/styles
$ mv src/app/globals.css src/styles/globals.css
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
src/app/page.tsx
export default function Home() {
return (
<main className="text-lg">
テストページ
</main>
)
}
src/app/layout.tsx
import '@/styles/globals.css'
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className="">{children}</body>
</html>
);
}
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
plugins: [],
};
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
+ "baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
コミットします。
$ pnpm build
$ git add .
$ git commit -m "新規にプロジェクトを作成し, 作業環境を構築"
shadcn-ui
の環境を構築
shadcn-ui
CLI を実行し、作業環境を構築します。
$ pnpm dlx shadcn-ui@latest init
プロンプトで確認されるので返信していきます。
✔ Would you like to use TypeScript (recommended)? … yes
✔ Which style would you like to use? › Default
✔ Which color would you like to use as base color? › Slate
✔ Where is your global CSS file? … src/styles/globals.css
✔ Would you like to use CSS variables for colors? … yes
✔ Where is your tailwind.config.js located? … tailwind.config.js
✔ Configure the import alias for components: … @/components
✔ Configure the import alias for utils: … @/lib/utils
✔ Are you using React Server Components? … yes
✔ Write configuration to components.json. Proceed? … yes
変更点を確認します。長いので折りたたんでおきます。
変更点の確認
src/styles/globals.css
が変更されました。
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+
+ --ring: 215 20.2% 65.1%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 0 85.7% 97.3%;
+
+ --ring: 217.2 32.6% 17.5%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
src/lib/utils.ts
が新規作成されました。
src/lib/utils.ts
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
components.json
が新規作成されました。
src/components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/styles/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
package.json
にパッケージが追加されています。
package.json
{
"name": "nextjs-shadcnui-contact-sample",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@types/node": "20.4.4",
"@types/react": "18.2.15",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.14",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.0.0",
"eslint": "8.45.0",
"eslint-config-next": "13.4.12",
+ "lucide-react": "^0.263.0",
"next": "13.4.12",
"postcss": "8.4.27",
"react": "18.2.0",
"react-dom": "18.2.0",
+ "tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
+ "tailwindcss-animate": "^1.0.6",
"typescript": "5.1.6"
}
}
コミットします。
$ pnpm build
$ git add .
$ git commit -m "shadcn/uiの環境を構築"
Toastを追加
Toast
を追加します。
パッケージをインストールし、実装します。
$ pnpm dlx shadcn-ui@latest add toast
$ pnpm dlx shadcn-ui@latest add button
ボタンをクリックしたら Toast が表示されるようにしたいので、自前でコンポーネントを作成します。
$ touch src/components/button.tsx
src/components/button.tsx
"use client"
import { Button } from "@/components/ui/button"
import { useToast } from "@/components/ui/use-toast"
export function CustomButton() {
const { toast } = useToast()
return (
<Button
variant="outline"
onClick={() => {
toast({
description: "Your message has been sent.",
})
}}
>
Show Toast
</Button>
)
}
<Toaster>
を配置します。
src/app/layout.tsx
import "@/styles/globals.css";
+import { Toaster } from "@/components/ui/toaster";
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className="">
+ <main>{children}</main>
+ <Toaster />
</body>
</html>
);
}
自前で作成下コンポーネントを配置します。
src/app/page.tsx
export default function Home() {
return (
<main className="text-lg">
- テストページ
+ <CustomButton />
</main>
)
}
ローカルサーバで動作確認をします。
$ pnpm dev
ボタンをクリックすると、右下に Toast が表示されました。
コミットします。
$ pnpm build
$ git add .
$ git commit -m "Toastを実装"
間違いそうな部分
続いて間違った使い方を確認します。
<Toaster />
の位置が <body>
の中にないと、エラーが発生します。
src/app/layout.tsx
import "@/styles/globals.css";
import { Toaster } from "@/components/ui/toaster";
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className="">
<main>{children}</main>
- <Toaster />
</body>
+ <Toaster />
</html>
);
}
ローカルサーバで実行すると以下のエラーが発生します。
まとめ
-
shadcn/ui
のToast
を利用する際に、<Toaster>
の位置が<body>
の中にないとエラーが発生します。 - 作業したプロジェクトは以下にあります。
Discussion