Aller au contenu principal

Module 6 – Liens et navigation

Niveau 5.2 – Laravel Inertia (React & Vue)


Objectif

À la fin de ce module vous saurez :

  • Utiliser le composant Link d’Inertia pour toute navigation interne (éviter les <a href> qui provoqueraient un rechargement complet).
  • Contrôler le comportement de la navigation avec preserveState et preserveScroll (conserver l’état du formulaire ou la position du scroll).
  • Faire des visites partielles (partial reloads) pour ne recharger que certaines props et alléger les réponses.
  • Utiliser router.visit (ou router.get) en JavaScript pour des navigations programmatiques (après soumission, redirection conditionnelle).

Nous donnons des exemples concrets : navbar avec Link, pagination avec preserveScroll, formulaire de filtre avec preserveState, et code React et Vue pour chaque cas.


Pourquoi ne pas utiliser un simple <a href> ?

En Inertia, chaque clic sur un lien interne doit être intercepté pour déclencher une requête XHR vers Laravel et mettre à jour le contenu de la page sans rechargement. Si vous utilisez une balise <a href="/dashboard"> classique, le navigateur fera une requête GET normale et rechargera toute la page : perte de l’état JavaScript, re-téléchargement des assets, flash blanc. Le composant Link d’Inertia :

  • intercepte le clic ;
  • envoie une requête XHR avec le header X-Inertia: true ;
  • reçoit la réponse (composant + props) et met à jour le DOM.

Règle : pour tout lien qui pointe vers une URL de votre application gérée par Inertia, utilisez <Link href="..."> (React) ou <Link :href="..."> (Vue). Réservez <a href> aux liens externes (autre domaine) ou pour forcer un rechargement volontaire (ex. « Ouvrir dans un nouvel onglet » avec target="_blank" ; dans ce cas le comportement Inertia ne s’applique pas).


React :

import { Link } from '@inertiajs/react';

// Lien simple
<Link href="/dashboard">Tableau de bord</Link>

// Lien avec paramètre (route nommée si Ziggy est installé)
<Link href={route('users.show', { user: user.id })}>Voir le profil</Link>

// Équivalent sans Ziggy (URL en dur)
<Link href={`/users/${user.id}`}>Voir le profil</Link>

// Classes CSS (comme sur un <a>)
<Link href="/settings" className="text-indigo-600 hover:underline">
Paramètres
</Link>

Vue :

<template>
<Link href="/dashboard">Tableau de bord</Link>
<Link :href="`/users/${user.id}`">Voir le profil</Link>
<Link href="/settings" class="text-indigo-600 hover:underline">
Paramètres
</Link>
</template>

<script setup>
import { Link } from '@inertiajs/vue3';
</script>

Le composant Link accepte les mêmes attributs qu’un <a> (href, class, id, etc.) et rend un <a> en HTML. La différence est le comportement au clic : interception par Inertia.


preserveState – garder l’état en naviguant

Par défaut, quand vous quittez une page (ex. liste d’utilisateurs avec un filtre saisi), puis vous revenez en arrière (bouton « Retour » du navigateur ou lien « Retour à la liste »), Inertia peut recharger la page et donc réinitialiser l’état (filtres, formulaire partiellement rempli, etc.). Si vous voulez que la page « se souvienne » de son état quand on revient, utilisez preserveState.

Exemple : page « Créer un utilisateur ». L’utilisateur remplit le formulaire, clique sur « Voir la liste » (Link vers /users), puis clique sur « Créer un utilisateur » (Link vers /users/create). Sans preserveState, le formulaire sera vide. Avec preserveState sur le Link vers /users/create, Inertia peut conserver l’état du composant de la page create (selon la version et la config), ce qui permet de retrouver les champs remplis.

React :

<Link href="/users/create" preserveState>
Créer un utilisateur
</Link>

Vue :

<Link href="/users/create" preserve-state>
Créer un utilisateur
</Link>

En Vue, les props sont souvent en kebab-case dans le template : preserve-state. Utile aussi pour des modales ou des onglets dont l’état doit rester en place quand on navigue ailleurs puis on revient.


preserveScroll – ne pas remonter en haut

Lors d’une navigation, Inertia remplace le contenu de la page et, par défaut, remet le scroll en haut (comportement classique d’une nouvelle page). Sur une liste paginée, si l’utilisateur clique sur « Page 2 », il peut être frustrant de se retrouver en haut de la liste au lieu de rester à la position des liens de pagination. preserveScroll indique à Inertia de ne pas modifier la position du scroll après la visite.

React – liens de pagination :

<Link href={users.prev_page_url} preserveScroll>
Page précédente
</Link>
<Link href={users.next_page_url} preserveScroll>
Page suivante
</Link>

Vue :

<Link :href="users.prev_page_url" preserve-scroll>Page précédente</Link>
<Link :href="users.next_page_url" preserve-scroll>Page suivante</Link>

Vous pouvez combiner : preserveState et preserveScroll sur le même Link si besoin.


Visites partielles (partial reloads)

Une page peut recevoir beaucoup de props (liste d’articles, catégories pour un filtre, stats, etc.). Lors d’une action qui ne change qu’une partie des données (ex. changement de page de pagination : seules les articles changent, pas les catégories), vous pouvez demander à Laravel de ne renvoyer que certaines clés de props. Cela réduit la taille de la réponse et peut accélérer la navigation.

Côté client – au lieu d’un simple Link, vous utilisez router.get (ou router.visit) avec l’option only :

React :

import { router } from '@inertiajs/react';

// Recharger uniquement les props 'articles' et 'filters'
router.get('/articles', { page: 2 }, {
only: ['articles', 'filters'],
preserveState: true,
});

Vue :

import { router } from '@inertiajs/vue3';

router.get('/articles', { page: 2 }, {
only: ['articles', 'filters'],
preserveState: true,
});

Côté Laravel : le contrôleur renvoie toujours toutes les props ; Inertia, côté client, ignore les clés qui ne sont pas dans only et garde les anciennes valeurs pour les autres. Ainsi, seules articles et filters sont mises à jour dans la page ; le reste (ex. categories) reste inchangé. Utile pour des listes lourdes ou des tableaux de bord avec plusieurs blocs de données.


Navigation programmatique – router.visit / router.get

Parfois vous voulez naviguer depuis le code (après une soumission de formulaire, après un clic sur un bouton qui fait un calcul puis redirige, etc.). Vous pouvez utiliser router.visit(url) ou router.get(url, queryParams, options).

React – après création d’un utilisateur, redirection dans le contrôleur ; si vous vouliez le faire côté client (par ex. après un appel API personnalisé) :

import { router } from '@inertiajs/react';

router.visit(route('users.index'));
// ou avec query string
router.get(route('users.index'), { created: 1 });

Vue :

import { router } from '@inertiajs/vue3';

router.visit(route('users.index'));
router.get(route('users.index'), { created: 1 });

router.post, router.put, router.patch, router.delete sont aussi disponibles (utilisés en interne par useForm). Vous pouvez les appeler manuellement pour des soumissions sans useForm (cas avancés).


import { Link } from '@inertiajs/react';

export default function AppLayout({ children }) {
return (
<div>
<nav>
<Link href="/">Accueil</Link>
<Link href="/dashboard">Dashboard</Link>
<Link href="/users">Utilisateurs</Link>
<Link href="/users/create" preserveState>
Nouvel utilisateur
</Link>
</nav>
<main>{children}</main>
</div>
);
}

Exemple complet : pagination avec preserveScroll (Vue)

<template>
<div>
<ul>
<li v-for="user in users.data" :key="user.id">
<Link :href="`/users/${user.id}`">{{ user.name }}</Link>
</li>
</ul>
<div class="pagination">
<Link
v-if="users.prev_page_url"
:href="users.prev_page_url"
preserve-scroll
>
Précédent
</Link>
<Link
v-if="users.next_page_url"
:href="users.next_page_url"
preserve-scroll
>
Suivant
</Link>
</div>
</div>
</template>

<script setup>
import { Link } from '@inertiajs/vue3';
defineProps({ users: Object });
</script>

À retenir

  • Toujours Link pour les liens internes à l’app Inertia ; <a> pour les liens externes ou ouverture dans un nouvel onglet.
  • preserveState : conserver l’état du composant (formulaire, filtres) quand on revient sur la page.
  • preserveScroll : ne pas remonter en haut après la visite (pagination, longues listes).
  • Visites partielles : router.get(url, params, { only: ['prop1', 'prop2'] }) pour ne mettre à jour que certaines props.
  • router.visit, router.get pour la navigation programmatique depuis le code.

Dans le prochain module, nous verrons les données partagées (utilisateur connecté, flash messages) via le middleware HandleInertiaRequests::share().