Gestion des erreurs

Dans le chapitre précédent, vous avez appris à muter des données en utilisant les Server Actions. Voyons maintenant comment gérer les erreurs avec élégance en utilisant les instructions try/catch de JavaScript et les API Next.js pour les exceptions non capturées.

Ajout de try/catch aux Server Actions

Commençons par ajouter les instructions try/catch de JavaScript à vos Server Actions pour vous permettre de gérer les erreurs avec élégance.

Si vous savez comment faire cela, prenez quelques minutes pour mettre à jour vos Server Actions, ou vous pouvez copier le code ci-dessous :

Notez comment redirect est appelé en dehors du bloc try/catch. Cela est dû au fait que redirect fonctionne en lançant une erreur, qui serait capturée par le bloc catch. Pour éviter cela, vous pouvez appeler redirect après try/catch. redirect ne serait accessible que si try réussit.

Nous gérons ces erreurs avec élégance en captant le problème de base de données et en retournant un message utile depuis notre Server Action.

Que se passe-t-il s'il y a une exception non capturée dans votre action ? Nous pouvons simuler cela en lançant manuellement une erreur. Par exemple, dans l'action deleteInvoice, lancez une erreur au début de la fonction :

/app/lib/actions.ts
export async function deleteInvoice(id: string) {
  throw new Error('Échec de la suppression de la facture');
 
  // Bloc de code inaccessible
  await sql`DELETE FROM invoices WHERE id = ${id}`;
  revalidatePath('/dashboard/invoices');
}

Lorsque vous essayez de supprimer une facture, vous devriez voir l'erreur en local. En production, vous voudrez afficher un message plus élégant à l'utilisateur lorsque quelque chose d'inattendu se produit.

C'est là qu'intervient le fichier error.tsx de Next.js. Assurez-vous de supprimer cette erreur ajoutée manuellement après les tests et avant de passer à la section suivante.

Gestion de toutes les erreurs avec error.tsx

Le fichier error.tsx peut être utilisé pour définir une limite d'interface utilisateur pour un segment de route. Il sert de capture globale pour les erreurs inattendues et vous permet d'afficher une interface de repli à vos utilisateurs.

Dans votre dossier /dashboard/invoices, créez un nouveau fichier appelé error.tsx et collez le code suivant :

/dashboard/invoices/error.tsx
'use client';
 
import { useEffect } from 'react';
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // Optionnellement enregistrer l'erreur dans un service de rapport d'erreurs
    console.error(error);
  }, [error]);
 
  return (
    <main className="flex h-full flex-col items-center justify-center">
      <h2 className="text-center">Quelque chose s'est mal passé !</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={
          // Tentative de récupération en re-rendant la route des factures
          () => reset()
        }
      >
        Réessayer
      </button>
    </main>
  );
}

Vous remarquerez quelques éléments dans le code ci-dessus :

  • "use client" - error.tsx doit être un composant client.
  • Il accepte deux props :
    • error : Cet objet est une instance de l'objet natif Error de JavaScript.
    • reset : Cette fonction permet de réinitialiser la limite d'erreur. Lorsqu'elle est exécutée, la fonction tentera de re-rendre le segment de route.

Lorsque vous essayez à nouveau de supprimer une facture, vous devriez voir l'interface suivante :

Le fichier error.tsx montrant les props qu'il accepte

Gestion des erreurs 404 avec la fonction notFound

Une autre façon de gérer les erreurs avec élégance est d'utiliser la fonction notFound. Alors que error.tsx est utile pour capturer les exceptions non capturées, notFound peut être utilisé lorsque vous essayez de récupérer une ressource qui n'existe pas.

Par exemple, visitez http://localhost:3000/dashboard/invoices/2e94d1ed-d220-449f-9f11-f0bbceed9645/edit.

Il s'agit d'un UUID fictif qui n'existe pas dans votre base de données.

Vous verrez immédiatement que error.tsx intervient car il s'agit d'une route enfant de /invoiceserror.tsx est défini.

Cependant, si vous voulez être plus précis, vous pouvez afficher une erreur 404 pour indiquer à l'utilisateur que la ressource qu'il essaie d'accéder n'a pas été trouvée.

Vous pouvez confirmer que la ressource n'a pas été trouvée en allant dans votre fonction fetchInvoiceById dans data.ts, et en affichant la facture retournée dans la console :

/app/lib/data.ts
export async function fetchInvoiceById(id: string) {
  try {
    // ...
 
    console.log(facture); // La facture est un tableau vide []
    return facture[0];
  } catch (error) {
    console.error('Erreur de base de données :', error);
    throw new Error('Échec de la récupération de la facture.');
  }
}

Maintenant que vous savez que la facture n'existe pas dans votre base de données, utilisons notFound pour la gérer. Naviguez vers /dashboard/invoices/[id]/edit/page.tsx, et importez { notFound } depuis 'next/navigation'.

Ensuite, vous pouvez utiliser une condition pour invoquer notFound si la facture n'existe pas :

/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 [facture, clients] = await Promise.all([
    fetchInvoiceById(id),
    fetchCustomers(),
  ]);
 
  if (!facture) {
    notFound();
  }
 
  // ...
}

Ensuite, pour afficher une interface d'erreur à l'utilisateur, créez un fichier not-found.tsx dans le dossier /edit.

Le fichier not-found.tsx dans le dossier edit

Dans le fichier not-found.tsx, collez le code suivant :

/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 Non trouvé</h2>
      <p>Impossible de trouver la facture demandée.</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"
      >
        Retour
      </Link>
    </main>
  );
}

Actualisez la route, et vous devriez maintenant voir l'interface suivante :

Page 404 Non trouvé

C'est quelque chose à garder à l'esprit, notFound prendra le pas sur error.tsx, donc vous pouvez l'utiliser lorsque vous voulez gérer des erreurs plus spécifiques !

Lecture complémentaire

Pour en savoir plus sur la gestion des erreurs dans Next.js, consultez la documentation suivante :

On this page