Next.js link et useRouter : navigation entre pages

Publié le 25/09/2024 - Ecrit par Antoine Bourin

4 minutes

Le composant <Link> de Next.js est un composant qui étend la balise HTML <a> et vous permet d'effectuer des navigations entre vos pages. 

L'une des fonctionnalités importantes de ce composant est notamment le prefetch de pages sur lequel nous nous pencherons ici.

Lorsque les changements de page font suite à un événement client, l'utilisation du hook useRouter permet d'ajouter, remplacer, faire un retour en avant ou en arrière dans l'historique de navigation de votre utilisateur.

Ce composant qui étend de la balise HTML <a> comporte plusieurs avantages supplémentaires dans son utilisation dans le cadre d'une application Next.js. 

Prefetch de pages

Cette fonctionnalité uniquement disponible en production permet à ce que, lorsqu'un lien proposé entre dans le viewport d'un utilisateur, la page cible soit directement pré-chargée.

Les données requises pour l'affichage de cette page vont être chargées en fond pour améliorer la vitesse de chargement et les performances d'affichage de la page lorsque l'utilisateur souhaitera y accéder.

Par défaut, le composant pré-charge la page de cette manière, suivant le type de route de votre cible :

  • S'il s'agit d'une route statique, toute la page sera pré-chargée, y compris les données nécessaires pour son chargement.
  • S'il s'agit d'une route dynamique, toutes les données des segments de la page seront chargées jusqu'à rencontrer la présence d'un fichier loading.js dans un segment.

Vous pouvez forcer le chargement total d'une route cible qu'elle soit statique ou dynamique avec la valeur true au props prefetch :

// La route cible sera chargée totalement peu importe qu'elle soit statique ou dynamique
import Link from 'next/link'
 
export default function Page() {
  return (
    <Link href="/dashboard" prefetch>
      Dashboard
    </Link>
  )
}

Remplacement d'URL

Comme la navigation avec le composant Link est cliente, vous pouvez décider d'inclure un changement d'URL dans l'historique de votre utilisateur ou non.

Pour se faire, vous pouvez utiliser le props replace. Ici, la route /user/profile remplacera la route actuelle de dashboard dans l'historique.

import Link from 'next/link'
 
export default function DashboardPage() {
  return (
    <Link href="/user/profile" prefetch>
      Profil
    </Link>
  )
}

Liens actifs avec le hook usePathname

Si vous souhaitez vérifier si le lien cible est actif, si la page cible est la même que la page actuellement visitée, vous pouvez utiliser le hook Next.js usePathname

On peut donc, grâce à la valeur du pathname récupéré, déterminer une class CSS en fonction par exemple :

'use client'
 
import { usePathname } from 'next/navigation'
import Link from 'next/link'

export default function Header() {
  const pathname = usePathname()

  return (
    <header>
      <Link href="/" className={pathname === '/' ? 'active' : ''}>
        Accueil
      </Link>
      <Link href="/contact" className={pathname === '/contact' ? 'active' : ''}>
        Contactez-nous
      </Link>
    </header>
  );
}

Utilisation du hook useRouter

Si vous souhaitez également porter des actions sur la navigation d'un utilisateur en fonction d'événements dans votre application, le hook useRouter vous le permet.

N'utilisez le hook useRouter que si vous y êtes contraint et que l'utilisation du composant <Link> n'est pas possible. Par exemple, dans le cas d'un événement client comme lorsque l'utilisateur a soumis un formulaire.

Ajout et remplacement d'URL

Comme pour l'utilisation du composant vu précédemment, vous pouvez, à l'aide de ce hook ajouter ou remplacer une URL dans l'historique de navigation. 

Par exemple, lors de la finalisation de création d'un produit :

'use client'
import { useRouter } from 'next/navigation'
import { createProduct } from '@actions/product'

export default function AddProduct() {
  const router = useRouter()

  const handleSubmit = async (data) => {
    const product = await createProduct(data)

    router.push(`/product/${product.id}`)
  }

  return (
    // ....
  )
}

De la même manière, vous pourriez utiliser la fonction replace au lieu de push pour ne pas ajouter de nouvelles entrées dans l'historique de navigation.

Rafraîchissement avec router.refresh

L'utilisation de router.refresh() permet de faire une nouvelle requête au serveur pour récupérer de nouveau les données de la page et effectuer un re-rendu des composants serveurs de celle-ci.

Les composants clients ne perdront pas leur état (qui avait été modifié par exemple avec le hook useState).

Le comportement de cette fonction est à ne pas confondre avec une utilisation de window.location.reload par exemple. Ici, uniquement les données serveurs de la page sont récupérées de nouveau et les composants serveurs re-rendus.

Pré-chargement d'une route

Vous pouvez également avec le hook useRouter effectuer un pré-chargement d'une route spécifique avec la fonction prefetch.

Cette fonction peut être utile lorsque vous déterminez à l'avance qu'un utilisateur accédera à une route par la suite. Les données de celle-ci seront pré-chargées et les performances de chargement seront ainsi réduites.

router.prefetch('/product/xxx')

Retour en avant et en arrière : back et forward

Vous pouvez utiliser les fonctions back() et forward() pour effectuer un retour en avant ou en arrière dans l'historique de navigation de l'utilisateur.

Par exemple, dans l'utilisation d'un bouton retour de vos pages :

'use client'
import { useRouter } from 'next/navigation'

export default function GoBack() {
  const router = useRouter()

  const handleBack = () => {
    router.back()
  }

  return (
    <button onClick={handleBack}>
      Retour
    </button>
  )
}

Envie d'en apprendre plus sur Next.js ?

Découvrez une formation Next.js complète :

  • Comprendre et créer un système de routage complet
  • Créer des routes statiques et dynamique
  • Maîtriser le rendu serveur et client
  • Utiliser tous les atouts majeurs proposés par le framework

Plus de 35 heures de contenu vidéo

Plus de 80 cours écrits