Next.js / Not Found хуудас

Not Found хуудас

Хэрэглэгч байхгүй хуудасны хаяг оруулах нь зайлшгүй тохиолддог. Анхны Next.js проект /random-page гэх мэт хаяг руу орвол автоматаар 404 хуудас харуулдаг — гэхдээ энэ хуудас маш энгийн харагддаг. Энэ хичээлд not-found.tsx ашиглан өөрийн 404 хуудас бүтээх аргыг сурна.

app/not-found.tsx — Нийтлэг 404 хуудас

app/ директорын шууд доор not-found.tsx файл үүсгэхэд бүх байхгүй хаягт тэр хуудас харагдана:

tsx
// app/not-found.tsx
import Link from "next/link";

export default function NotFoundPage() {
  return (
    <main className="flex flex-col items-center justify-center min-h-screen bg-[#0b1120] gap-6 px-4">
      <div className="text-center">
        <p className="text-8xl font-bold text-[#1e293b]">404</p>
        <h1 className="text-2xl font-bold text-white mt-2">Хуудас олдсонгүй</h1>
        <p className="text-slate-400 mt-2 max-w-sm">
          Та хайж байгаа хуудас нүүлгэгдсэн, устгагдсан, эсвэл огт байгаагүй
          байна.
        </p>
      </div>
      <Link
        href="/"
        className="px-6 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-500 transition-colors"
      >
        Нүүр хуудас руу буцах
      </Link>
    </main>
  );
}

notFound() функц — Программаар дуудах

Dynamic хуудасд байхгүй slug ирвэл notFound() функцийг шууд дуудаж болно. Энэ функц дуусгалтаас хойшхи кодыг ажиллуулахгүйгээр not-found.tsx хуудсыг харуулна:

tsx
// app/courses/[courseSlug]/page.tsx
import { notFound } from "next/navigation";
import { getCourse } from "@/lib/courses";

interface Props {
  params: Promise<{ courseSlug: string }>;
}

export default async function CoursePage({ params }: Props) {
  const { courseSlug } = await params;
  const course = await getCourse(courseSlug);

  // Курс олдоогүй бол 404 харуул
  if (!course) {
    notFound();
  }

  // Энэ мөрөнд хүрэхэд course заавал байна гэдгийг TypeScript мэднэ
  return (
    <main>
      <h1 className="text-white text-2xl font-bold">{course.title}</h1>
      <p className="text-slate-400">{course.description}</p>
    </main>
  );
}

notFound() нь never төрөл буцаадаг тул TypeScript тухайн мөрөнд хүрсний дараа утга заавал байна гэдгийг ойлгодог — course! гэж бичих шаардлагагүй.

Nested not-found.tsx

error.tsx шиг not-found.tsx мөн давхарлагдана. /courses директорт өөрийн not-found.tsx нэмж болно:

tsx
// app/courses/not-found.tsx
import Link from "next/link";

export default function CourseNotFound() {
  return (
    <div className="flex flex-col items-center justify-center min-h-[400px] gap-4 px-4">
      <div className="text-center">
        <h2 className="text-xl font-bold text-white">Курс олдсонгүй</h2>
        <p className="text-slate-400 mt-2 text-sm">
          Энэ курс байхгүй эсвэл нэр өөрчлөгдсөн байна.
        </p>
      </div>
      <Link href="/courses" className="text-indigo-400 hover:underline text-sm">
        ← Бүх сургалтууд руу буцах
      </Link>
    </div>
  );
}
tsx
// app/courses/[courseSlug]/page.tsx — notFound() дуудахад
// app/courses/not-found.tsx ашиглагдана (app/not-found.tsx биш)
import { notFound } from "next/navigation";

export default async function CoursePage({
  params,
}: {
  params: Promise<{ courseSlug: string }>;
}) {
  const { courseSlug } = await params;
  const course = await getCourse(courseSlug);

  if (!course) notFound(); // → app/courses/not-found.tsx харуулна

  return <h1>{course.title}</h1>;
}

metadata 404 хуудасд

404 хуудасд ч мөн metadata нэмж болно:

tsx
// app/not-found.tsx
import type { Metadata } from "next";
import Link from "next/link";

export const metadata: Metadata = {
  title: "404 — Хуудас олдсонгүй | ulaanbaatar.app",
};

export default function NotFoundPage() {
  return (
    <main className="flex flex-col items-center justify-center min-h-screen bg-[#0b1120] gap-6 px-4">
      <div className="text-center">
        <p className="text-8xl font-bold text-[#1e293b] select-none">404</p>
        <h1 className="text-2xl font-bold text-white mt-4">Хуудас олдсонгүй</h1>
        <p className="text-slate-400 mt-2">
          Холбоос буруу эсвэл хуудас устгагдсан байна.
        </p>
      </div>
      <div className="flex gap-3">
        <Link
          href="/"
          className="px-5 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-500 transition-colors text-sm"
        >
          Нүүр хуудас
        </Link>
        <Link
          href="/courses"
          className="px-5 py-2 bg-[#1e293b] text-slate-300 rounded-lg hover:bg-[#334155] transition-colors text-sm"
        >
          Сургалтууд
        </Link>
      </div>
    </main>
  );
}

notFound() ба error.tsx-н ялгаа

| | notFound() | throw new Error() | | ------------- | -------------------- | ----------------------- | | HTTP статус | 404 | 500 | | Харуулах файл | not-found.tsx | error.tsx | | Хэзээ ашиглах | Өгөгдөл олдоогүй үед | Систем алдаа гарсан үед | | reset товч | Байхгүй | Байна |

Курс, хичээл, хэрэглэгч олдоогүй тохиолдолд notFound() — өгөгдлийн сан унасан, сүлжээ тасарсан тохиолдолд throw new Error() ашигла.

Дараагийн хичээлд:

Server дээр өгөгдөл татах аргуудыг судална. fetch, файл систем, Supabase-с шууд уншиж, Server Component-д хэрхэн ашиглах практик жишээгээр ойлгоно.