1、全局错误页
app/error.tsx
'use client'
import { Button } from "@/components/ui/button"
import { AlertTriangle } from "lucide-react"
import Link from "next/link"
const ErrorPage = () => {
return (
<div className="h-screen flex flex-col gap-y-2 items-center justify-center">
<AlertTriangle className="text-muted-foreground"/>
<p className="text-sm text-muted-foreground">
Oops! Something went wrong.
</p>
<Button variant='secondary'>
<Link href='/'>
Back to home
</Link>
</Button>
</div>
)
}
export default ErrorPage
2、页面错误页
components/page-error.tsx
import { AlertTriangle } from "lucide-react";
interface PageErrorProps {
message: string;
}
const PageError = ({
message="Somthing went wrong"
}:PageErrorProps) => {
return (
<div className="flex flex-col items-center justify-center h-full">
<AlertTriangle className="size-6 text-muted-foreground mb-2"/>"
<p className="text-sm font-medium text-muted-foreground">
{message}
</p>
</div>
);
};
export default PageError;
使用:
import PageError from "@/components/page-error";
import PageLoader from "@/components/page-loader";
if(isLoading){
return <PageLoader/>
}
if(!initialValues) {
return <PageError message="Project not found"/>
};
3、Not-Found页
/app/not-found.tsx
'use client';
import { useRouter } from 'next/navigation';
import { Button } from '@/components/ui/button';
export default function NotFound() {
const router = useRouter();
return (
<div className="absolute left-1/2 top-1/2 mb-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center text-center">
<span className="bg-gradient-to-b from-foreground to-transparent bg-clip-text text-[10rem] font-extrabold leading-none text-transparent">
404
</span>
<h2 className="font-heading my-2 text-2xl font-bold">
Something's missing
</h2>
<p>
Sorry, the page you are looking for doesn't exist or has been
moved.
</p>
<div className="mt-8 flex justify-center gap-2">
<Button onClick={() => router.back()} variant="default" size="lg">
Go back
</Button>
<Button
onClick={() => router.push('/dashboard')}
variant="ghost"
size="lg"
>
Back to Home
</Button>
</div>
</div>
);
}
4、路由loading页
app/loading.tsx
import { Loader } from "lucide-react"
const LoadingPage = () => {
return (
<div className="h-screen flex flex-colitems-center justify-center">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
)
}
export default LoadingPage
5、组件loading页
手工控制加载器:
components/page-load.tsx
import { Loader } from "lucide-react";
const PageLoader = () => {
return (
<div className="flex items-center justify-center h-full">
<Loader className="size-6 animate-spin text-muted-foreground"/>
</div>
);
};
export default PageLoader;
使用:
import PageLoader from "@/components/custom/page-loader";
if(isLoading){
return <PageLoader/>
}
6、TopLoading (路由loading)
安装
npm install nextjs-toploader
使用
在 app/layout.js 中使用(适用于 app 文件夹结构)
在 RootLayout 的 <body> 标签内添加 <NextTopLoader />:
import NextTopLoader from 'nextjs-toploader';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<NextTopLoader />
{children}
</body>
</html>
);
}
);
}
或者: //表示加载指示器会显示出来
使用 useRouter 钩子触发 TopLoader
在 app/layout.js 中使用(适用于 app 文件夹结构)
导入 useRouter 钩子并使用:
import { useRouter } from 'nextjs-toploader/app';
const router = useRouter();
router.push('/some-page');
7、弹出消息
app/layout.tsx中
import { Toaster } from "@/components/ui/toaster"
<body className={'overflow-hidden'}>apter>
{children}
<Toaster/>
</body>
使用
"use client"
import { useToast } from "@/hooks/use-toast"
import { Button } from "@/components/ui/button"
import { ToastAction } from "@/components/ui/toast"
function ToastDemo() {
const { toast } = useToast()
return (
<Button
variant="outline"
onClick={() => {
toast({
className: 'top-0 right-0 flex fixed md:max-w-[420px] md:top-4 md:right-4',
variant: "success",
title: "Scheduled: Catch up ",
description: "Friday, February 10, 2023 at 5:57 PM",
action: (
<ToastAction altText="Goto schedule to undo">Undo</ToastAction>
),
})
}}
>
Add to calendar
</Button>
)
}
export default ToastDemo