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 :
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 :
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 :
refest appliquée au conteneur des sections. Le hook associe les enfants directs par index au tableauanchors.scroll: falsedansrouter.pushempêche le défilement automatique de Next.js.shallow: trueoptimise 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.
Comportement de l'application
L'implémentation résultante offre :
- Un accès direct aux liens comme
/aboutatterrissant 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
useAnchorObserverautomatise entièrement la synchronisation bidirectionnelle du défilement et de l'URL. - Désactiver
scrollRestorationest essentiel pour éviter les conflits. - Les routes attrape-tout dans le routeur Pages conviennent à une navigation de type SPA.
shallow: true+scroll: falseminimisent les re-rendus.- La prise en charge de l'historique du navigateur et du SEO est intégrée.
— Editorial Team
Aucun commentaire pour le moment.