2、next.js全局配置页 (next.js14+react19+shadcn后台管理)

131 阅读1分钟

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&apos;s missing
      </h2>
      <p>
        Sorry, the page you are looking for doesn&apos;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