éviter.fr Le guide anti-pièges
Technologie

Comment éviter le rafraîchissement d’une page web

Comment éviter le rafraîchissement d’une page web

La réponse dépend de ce que l’on veut empêcher, et il faut distinguer trois cas que l’on confond souvent. Pour un formulaire qui recharge la page à la validation, la solution est event.preventDefault() associé à un envoi asynchrone. Pour éviter une perte de données quand l’utilisateur quitte, c’est l’évènement beforeunload. Pour changer de contenu sans recharger, c’est l’API History.

Un point mérite d’être posé d’emblée : on ne peut pas empêcher un utilisateur de rafraîchir sa page. La touche F5, le bouton du navigateur et le geste de balayage sur mobile restent sous son contrôle exclusif, et c’est une bonne chose. Ce que l’on peut faire, c’est éviter les rechargements que le code provoque lui-même, et limiter leurs conséquences.

Le formulaire, cause numéro un

Par défaut, la validation d’un formulaire déclenche une requête et un rechargement complet de la page. C’est le comportement historique du web, et c’est celui qu’il faut neutraliser pour obtenir une interface qui réagit sans clignoter.

document.querySelector('form').addEventListener('submit', function (event) {
  event.preventDefault();
  // traitement, puis envoi asynchrone
});

L’appel à preventDefault annule le comportement par défaut du navigateur. Il ne fait rien d’autre : les données ne partent nulle part tant que vous n’avez pas écrit l’envoi vous-même, ce qui est l’oubli le plus fréquent chez les débutants.

Envoyer les données sans recharger

Une fois le rechargement bloqué, il faut transmettre les données autrement. La méthode fetch remplit ce rôle et remplace avantageusement les anciennes approches, avec une syntaxe nettement plus lisible.

form.addEventListener('submit', async (event) => {
  event.preventDefault();
  const reponse = await fetch('/api/enregistrer', {
    method: 'POST',
    body: new FormData(form)
  });
  const resultat = await reponse.json();
  // mettre a jour l'interface avec resultat
});

L’objet FormData récupère automatiquement tous les champs du formulaire, ce qui évite de les lire un par un. Pensez à traiter le cas d’erreur : sans gestion d’échec, l’utilisateur clique et ne voit rien se passer, ce qui est pire qu’un rechargement.

Désactiver le bouton pendant l’envoiBloquer le rechargement supprime le repère visuel qu’il constituait. Sans indicateur, l’utilisateur clique plusieurs fois et crée des doublons en base. Désactivez le bouton dès la soumission et affichez un état de chargement, puis réactivez-le à la réponse.

Avertir avant de quitter la page

Lorsque l’utilisateur a saisi des données non enregistrées, on peut lui demander confirmation avant qu’il ne ferme l’onglet ou ne rafraîchisse. L’évènement beforeunload sert à cela.

window.addEventListener('beforeunload', (event) => {
  if (modificationsNonEnregistrees) {
    event.preventDefault();
    event.returnValue = '';
  }
});

Le message affiché est imposé par le navigateur et ne peut pas être personnalisé, précaution destinée à empêcher les abus. Cet avertissement ne se déclenche par ailleurs que si l’utilisateur a interagi avec la page, ce qui explique qu’il paraisse parfois ne pas fonctionner en test.

À utiliser avec parcimonie : une page qui demande confirmation à chaque sortie devient rapidement irritante. Réservez-le aux formulaires longs et aux éditeurs de contenu, là où la perte serait réellement coûteuse. Le choix d’un téléviseur repose de la même façon sur des paramètres invisibles, la durée de support du système comptant davantage que la dalle.

Changer de contenu sans recharger

Pour une navigation interne, l’API History permet de modifier l’adresse affichée et l’historique sans provoquer de requête. C’est le mécanisme sur lequel reposent les applications à page unique.

history.pushState({ page: 2 }, '', '/articles/page-2');
window.addEventListener('popstate', (event) => {
  // rendre a nouveau le contenu correspondant a event.state
});

L’écoute de popstate est indispensable et souvent oubliée : sans elle, le bouton retour du navigateur change l’adresse sans changer le contenu affiché, ce qui produit une incohérence déroutante pour l’utilisateur.

BesoinOutilPiège courant
Formulaire sans rechargementpreventDefault et fetchOublier d’envoyer les données
Éviter la perte de saisiebeforeunloadMessage non personnalisable
Navigation interneAPI HistoryNe pas écouter popstate
Doubles envoisDésactivation du boutonOublier de le réactiver en cas d’erreur
Sauvegarde de secourslocalStorageNe jamais purger après envoi

La sauvegarde de secours

Plutôt que de lutter contre le rafraîchissement, la meilleure approche consiste souvent à le rendre inoffensif. Enregistrer la saisie en cours dans le stockage local du navigateur permet de la restaurer si la page est rechargée, volontairement ou non.

Cette solution a l’avantage de couvrir tous les cas de figure, y compris la fermeture accidentelle de l’onglet, la coupure de connexion et le plantage du navigateur, contre lesquels aucun code ne peut rien. Il faut penser à effacer ces données une fois l’enregistrement réussi.

Ce qu’il ne faut plus faire

Deux pratiques anciennes sont à écarter. La balise meta refresh, qui recharge la page à intervalle fixe, casse le bouton retour et pose des problèmes d’accessibilité. Elle doit être remplacée par une mise à jour ciblée du contenu concerné.

Les tentatives de blocage de la touche F5 ou du menu contextuel relèvent de la même erreur de conception : elles ne fonctionnent pas de façon fiable, dégradent l’expérience et entrent en conflit avec les outils d’accessibilité. La bonne réponse est de rendre le rechargement sans conséquence, pas de chercher à l’interdire. Une montre illustre cette préférence pour la robustesse, l’étanchéité annoncée y dépendant de joints qui vieillissent et non d’une garantie permanente.