Retour à l'accueil

Navigation par ancre dans Next.js avec useAnchorObserver

L'article décrit l'implémentation de la navigation par ancre dans une application Next.js monopage utilisant le hook useAnchorObserver. La synchronisation du défilement et de l'URL est automatisée, support de l'historique du navigateur et du SEO. Code complet avec paramètres fourni.

Application monopage sur Next.js : navigation par ancre sans bugs
Advertisement 728x90

Navigation par ancres dans une application monopage Next.js

Dans les applications monopage Next.js, la navigation par ancres permet des transitions fluides entre les sections sans recharger la page. Le hook useAnchorObserver de la bibliothèque react-use-observer-hooks automatise la synchronisation du défilement et de l'URL : il détecte la section visible pendant le défilement et fait défiler jusqu'à l'ancre lorsque l'adresse change.

Le mécanisme fonctionne dans les deux sens : le défilement met à jour l'URL via IntersectionObserver, tandis que les changements d'URL (provenant de clics ou du bouton retour) déclenchent le défilement vers la section. Cela évite les boucles de rétroaction et garantit une gestion correcte de l'historique du navigateur.

Configuration du projet

Utilisez Next.js 15 avec le routeur Pages, React 19 et Tailwind CSS v4. Installez la dépendance :

Google AdInline article slot
npm install react-use-observer-hooks

Désactivez la restauration du défilement intégrée dans next.config.ts pour éviter les conflits avec le hook :

const nextConfig = {
  experimental: {
    scrollRestoration: false,
  },
};

Créez une route attrape-tout [[...slug]].tsx pour gérer les chemins comme /, /about, /contact sur une seule page.

Code de la page principale

Définissez un tableau de sections avec href, label et composants :

Google AdInline article slot
import { useAnchorObserver } from 'react-use-observer-hooks';
import { useRouter } from 'next/router';

const SECTIONS = [
  { href: '/',        label: 'Accueil',    Component: HomeSection },
  { href: '/about',   label: 'À propos',   Component: AboutSection },
  { href: '/contact', label: 'Nous rejoindre', Component: ContactSection },
];

export default function Page() {
  const router = useRouter();

  const { ref, focusedAnchor } = useAnchorObserver<HTMLDivElement>({
    anchors: SECTIONS.map(s => s.href),
    currentAnchor: router.asPath,
    onAnchorChange: (anchor) => {
      router.push(anchor, undefined, { scroll: false, shallow: true });
    },
  });

  return (
    <>
      <Navbar sections={SECTIONS} activeHref={focusedAnchor} />

      <div ref={ref}>
        {SECTIONS.map(({ href, Component }) => (
          <section key={href} style={{ minHeight: '100vh' }}>
            <Component />
          </section>
        ))}
      </div>
    </>
  );
}

Aspects clés :

  • ref est appliquée au conteneur des sections. Le hook associe les enfants directs par index au tableau anchors.
  • scroll: false dans router.push empêche le défilement automatique de Next.js.
  • shallow: true optimise la navigation sans re-rendus côté serveur.

Composant de navigation

La barre de navigation utilise <Link> avec les mêmes options :

import Link from 'next/link';

export const Navbar = ({ sections, activeHref }) => (
  <nav>
    {sections.map(({ href, label }) => (
      <Link
        key={href}
        href={href}
        scroll={false}
        shallow
        className={activeHref === href ? 'active' : ''}
      >
        {label}
      </Link>
    ))}
  </nav>
);

focusedAnchor met automatiquement en évidence l'élément actif en fonction de la section visible.

Google AdInline article slot

Comportement de l'application

L'implémentation résultante offre :

  • Un accès direct aux liens comme /about atterrissant dans la bonne section.
  • Une fonctionnalité correcte du bouton retour du navigateur.
  • Une indexation par les moteurs de recherche avec des URL uniques.
  • Une synchronisation du menu avec le contenu visible.

Points clés

  • Le hook useAnchorObserver automatise entièrement la synchronisation bidirectionnelle du défilement et de l'URL.
  • Désactiver scrollRestoration est essentiel pour éviter les conflits.
  • Les routes attrape-tout dans le routeur Pages conviennent à une navigation de type SPA.
  • shallow: true + scroll: false minimisent les re-rendus.
  • La prise en charge de l'historique du navigateur et du SEO est intégrée.

— Editorial Team

Advertisement 728x90

Lire ensuite