Fehlerbehandlung

Im vorherigen Kapitel haben Sie gelernt, wie Sie Daten mit Server Actions mutieren können. Sehen wir uns nun an, wie Sie Fehler elegant mit JavaScripts try/catch-Anweisungen und Next.js APIs für unbehandelte Ausnahmen handhaben können.

Hinzufügen von try/catch zu Server Actions

Zuerst fügen wir JavaScripts try/catch-Anweisungen zu Ihren Server Actions hinzu, um Fehler elegant behandeln zu können.

Wenn Sie wissen, wie das geht, nehmen Sie sich ein paar Minuten Zeit, um Ihre Server Actions zu aktualisieren, oder kopieren Sie den folgenden Code:

Beachten Sie, dass redirect außerhalb des try/catch-Blocks aufgerufen wird. Das liegt daran, dass redirect durch das Auslösen eines Fehlers funktioniert, der vom catch-Block abgefangen würde. Um dies zu vermeiden, können Sie redirect nach try/catch aufrufen. redirect wäre nur erreichbar, wenn try erfolgreich ist.

Wir behandeln diese Fehler elegant, indem wir das Datenbankproblem abfangen und eine hilfreiche Nachricht von unserer Server Action zurückgeben.

Was passiert, wenn es eine unbehandelte Ausnahme in Ihrer Action gibt? Wir können dies simulieren, indem wir manuell einen Fehler auslösen. Zum Beispiel in der deleteInvoice-Action einen Fehler am Anfang der Funktion auslösen:

/app/lib/actions.ts
export async function deleteInvoice(id: string) {
  throw new Error('Failed to Delete Invoice');
 
  // Unerreichbarer Codeblock
  await sql`DELETE FROM invoices WHERE id = ${id}`;
  revalidatePath('/dashboard/invoices');
}

Wenn Sie versuchen, eine Rechnung zu löschen, sollten Sie den Fehler auf localhost sehen. In der Produktion möchten Sie dem Benutzer eine elegantere Nachricht anzeigen, wenn etwas Unerwartetes passiert.

Hier kommt die Next.js error.tsx-Datei ins Spiel. Stellen Sie sicher, dass Sie diesen manuell hinzugefügten Fehler nach dem Testen und vor dem nächsten Abschnitt entfernen.

Behandlung aller Fehler mit error.tsx

Die error.tsx-Datei kann verwendet werden, um eine UI-Grenze für ein Routensegment zu definieren. Sie dient als Auffangbecken für unerwartete Fehler und ermöglicht es Ihnen, eine Fallback-UI für Ihre Benutzer anzuzeigen.

Erstellen Sie in Ihrem /dashboard/invoices-Ordner eine neue Datei namens error.tsx und fügen Sie den folgenden Code ein:

/dashboard/invoices/error.tsx
'use client';
 
import { useEffect } from 'react';
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // Optional: Fehler an einen Fehlerberichtsdienst senden
    console.error(error);
  }, [error]);
 
  return (
    <main className="flex h-full flex-col items-center justify-center">
      <h2 className="text-center">Etwas ist schiefgelaufen!</h2>
      <button
        className="mt-4 rounded-md bg-blue-500 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-400"
        onClick={
          // Versuch, durch erneutes Rendern der Rechnungsroute wiederherzustellen
          () => reset()
        }
      >
        Erneut versuchen
      </button>
    </main>
  );
}

Es gibt ein paar Dinge, die Ihnen am obigen Code auffallen werden:

  • "use client" - error.tsx muss eine Client-Komponente sein.
  • Es akzeptiert zwei Props:
    • error: Dieses Objekt ist eine Instanz von JavaScripts nativen Error-Objekt.
    • reset: Dies ist eine Funktion zum Zurücksetzen der Fehlergrenze. Bei Ausführung versucht die Funktion, das Routensegment erneut zu rendern.

Wenn Sie erneut versuchen, eine Rechnung zu löschen, sollten Sie die folgende UI sehen:

Die error.tsx-Datei zeigt die Props, die sie akzeptiert

Behandlung von 404-Fehlern mit der notFound-Funktion

Eine weitere Möglichkeit, Fehler elegant zu behandeln, ist die Verwendung der notFound-Funktion. Während error.tsx nützlich für unbehandelte Ausnahmen ist, kann notFound verwendet werden, wenn Sie versuchen, eine Ressource abzurufen, die nicht existiert.

Besuchen Sie zum Beispiel http://localhost:3000/dashboard/invoices/2e94d1ed-d220-449f-9f11-f0bbceed9645/edit.

Dies ist eine gefälschte UUID, die nicht in Ihrer Datenbank existiert.

Sie werden sofort sehen, dass error.tsx greift, da dies eine Unterroute von /invoices ist, wo error.tsx definiert ist.

Wenn Sie jedoch spezifischer sein möchten, können Sie einen 404-Fehler anzeigen, um dem Benutzer mitzuteilen, dass die Ressource, auf die er zugreifen möchte, nicht gefunden wurde.

Sie können bestätigen, dass die Ressource nicht gefunden wurde, indem Sie in Ihre fetchInvoiceById-Funktion in data.ts gehen und die zurückgegebene invoice ausgeben:

/app/lib/data.ts
export async function fetchInvoiceById(id: string) {
  try {
    // ...
 
    console.log(invoice); // Invoice ist ein leeres Array []
    return invoice[0];
  } catch (error) {
    console.error('Datenbankfehler:', error);
    throw new Error('Fehler beim Abrufen der Rechnung.');
  }
}

Jetzt, da Sie wissen, dass die Rechnung nicht in Ihrer Datenbank existiert, verwenden wir notFound, um dies zu behandeln. Navigieren Sie zu /dashboard/invoices/[id]/edit/page.tsx und importieren Sie { notFound } von 'next/navigation'.

Dann können Sie eine Bedingung verwenden, um notFound aufzurufen, wenn die Rechnung nicht existiert:

/dashboard/invoices/[id]/edit/page.tsx
import { fetchInvoiceById, fetchCustomers } from '@/app/lib/data';
import { notFound } from 'next/navigation';
 
export default async function Page(props: { params: Promise<{ id: string }> }) {
  const params = await props.params;
  const id = params.id;
  const [invoice, customers] = await Promise.all([
    fetchInvoiceById(id),
    fetchCustomers(),
  ]);
 
  if (!invoice) {
    notFound();
  }
 
  // ...
}

Erstellen Sie dann eine not-found.tsx-Datei im /edit-Ordner, um die Fehler-UI dem Benutzer anzuzeigen.

Die not-found.tsx-Datei im edit-Ordner

Fügen Sie in der not-found.tsx-Datei den folgenden Code ein:

/dashboard/invoices/[id]/edit/not-found.tsx
import Link from 'next/link';
import { FaceFrownIcon } from '@heroicons/react/24/outline';
 
export default function NotFound() {
  return (
    <main className="flex h-full flex-col items-center justify-center gap-2">
      <FaceFrownIcon className="w-10 text-gray-400" />
      <h2 className="text-xl font-semibold">404 Nicht gefunden</h2>
      <p>Die angeforderte Rechnung konnte nicht gefunden werden.</p>
      <Link
        href="/dashboard/invoices"
        className="mt-4 rounded-md bg-blue-500 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-400"
      >
        Zurück
      </Link>
    </main>
  );
}

Aktualisieren Sie die Route, und Sie sollten jetzt die folgende UI sehen:

404 Nicht gefunden Seite

Beachten Sie, dass notFound Vorrang vor error.tsx hat, sodass Sie es verwenden können, wenn Sie spezifischere Fehler behandeln möchten!

Weiterführende Literatur

Um mehr über Fehlerbehandlung in Next.js zu erfahren, lesen Sie die folgende Dokumentation:

On this page