Tous les articlesFront-end & UI

React, Next.js, TypeScript : quelles erreurs les développeurs commettent-ils le plus souvent ?

Sommaire

Quelles erreurs React reviennent dans presque toutes les bases de code ?

L'erreur la plus répandue est l'usage de useEffect pour calculer un état dérivé. Un total de panier ou une liste filtrée se calcule pendant le rendu, pas dans un effet. La documentation React y consacre une page entière : You Might Not Need an Effect. Un effet superflu déclenche un rendu supplémentaire et fait apparaître des états intermédiaires incohérents à l'écran. Le test pratique avant d'écrire un useEffect : si l'effet ne synchronise pas le composant avec un système externe (réseau, DOM, abonnement), il n'a pas de raison d'exister.

La deuxième erreur est la duplication d'état. Le même objet métier existe à la fois dans un state local et dans le cache d'une librairie de requêtes. Deux sources de vérité, deux occasions de désynchronisation. La règle est simple : une donnée serveur vit dans le cache de requêtes (TanStack Query ou équivalent), une donnée d'interface vit au plus près du composant qui l'utilise.

Troisième erreur : les key instables dans les listes. Utiliser l'index du tableau comme key casse la réconciliation dès que la liste est triée ou filtrée. Le symptôme typique en production : un champ de formulaire qui affiche la valeur d'une autre ligne après une suppression. La key doit être un identifiant stable de la donnée elle-même.

80 %
des projets React audités par Athenix contiennent des useEffect superflus

Quels pièges sont spécifiques à Next.js et à l'App Router ?

Le piège le plus répandu : placer la directive use client trop haut dans l'arborescence. Toute la descendance du composant devient cliente, le bundle grossit d'autant et les Server Components ne servent plus à rien. La directive se place au plus bas de l'arbre, sur le composant interactif précis — un champ de recherche ou un bouton — jamais sur la page entière.

Deuxième piège : le cache. Next.js empile quatre couches : mémoïsation de requête, cache de données, cache de route complet et cache du routeur côté client. Leur comportement par défaut a changé entre les versions 13 et 15. Résultat fréquent en production : des données périmées affichées après une mutation. La documentation officielle sur le caching détaille chaque couche [SOURCE À VÉRIFIER : URL selon la version courante des docs]. Le correctif dépend de la version installée : une stratégie de revalidation écrite pour la v14 ne se comporte pas de la même façon en v13.

Troisième piège : les secrets côté client. Une variable d'environnement lue dans un composant client sans le préfixe NEXT_PUBLIC_ vaut undefined. L'inverse est pire : un secret préfixé NEXT_PUBLIC_ part dans le bundle JavaScript téléchargé par chaque visiteur. L'analyse du bundle après next build devrait précéder chaque mise en production.

TypeScript : quand le typage devient-il une illusion de sécurité ?

Un projet TypeScript avec strict à false dans le tsconfig.json n'offre presque aucune garantie. Les options regroupées sous le mode strict, dont strictNullChecks, éliminent la majorité des erreurs « undefined is not a function » constatées en production. C'est le premier fichier à ouvrir sur un projet existant. Sur une base ancienne, l'activation peut être progressive : strict à true au niveau global, puis traitement des erreurs répertoire par répertoire, en commençant par le code métier.

Le deuxième symptôme : any et as aux frontières du système. Une réponse d'API castée avec « as User » n'est pas validée — le compilateur croit ce qu'on lui affirme. La correction : valider au runtime avec un schéma (Zod ou équivalent) et laisser TypeScript inférer le type depuis ce schéma. Un point de validation unique par frontière : API externe, formulaire, stockage local et paramètres d'URL.

Troisième symptôme : les types dupliqués à la main. Le type User défini côté back, recopié côté front, puis divergent après quelques sprints. La source de vérité doit être unique : génération depuis un contrat OpenAPI, ou package de types partagé dans un monorepo.

Tableau récapitulatif : erreur, symptôme, correction

Ce tableau condense les défauts décrits ci-dessus. Chaque correction s'applique sans réécriture du projet.

ErreurSymptôme en productionCorrection
useEffect pour un état dérivérendus multiples, valeurs incohérentescalcul pendant le rendu
use client en haut d'arbrebundle lourd, interactivité lentedirective au plus bas de l'arbre
cache Next.js laissé par défautdonnées périmées après mutationrevalidation explicite par route
key={index} dans les listeschamps de formulaire mélangésidentifiant stable de la donnée
strict désactivé dans tsconfigerreurs undefined chez les utilisateursactiver strict, migrer fichier par fichier
as sur les réponses d'APIcrash sur payload inattenduvalidation runtime par schéma
types dupliqués back/frontdivergence silencieuse des modèlessource de types unique

Comment corriger ces erreurs sur une base de code existante ?

La réécriture complète est presque toujours une mauvaise décision : coûteuse, longue, et elle reproduit les mêmes défauts si la discipline de l'équipe ne change pas. La démarche qu'applique une équipe dédiée Athenix sur une base existante suit cinq étapes ordonnées.

  1. Auditer le tsconfig.json et la configuration ESLint : activer strict et passer les règles react-hooks en niveau erreur, pas en warning.
  2. Traiter les erreurs révélées fichier par fichier, en commençant par les frontières de données (API, formulaires).
  3. Mesurer le poids du bundle par route et redescendre les directives use client dans l'arbre de composants.
  4. Couvrir les parcours qui génèrent du revenu par des tests d'intégration avant tout refactoring.
  5. Bloquer la régression en CI : le lint et le typecheck font échouer le build.

Pour une application héritée d'un prestataire ou générée par IA, la démarche est identique : c'est le point de départ d'une reprise en TMA. Délai constaté chez Athenix pour ce type de fiabilisation : 1 a 3 semaines

Questions fréquentes

Faut-il réécrire une application React mal typée ?

Non, dans la majorité des cas. L'activation progressive du mode strict, fichier par fichier, corrige le typage sans interrompre les livraisons. La réécriture ne se justifie que si le framework lui-même est en fin de vie.

Le mode strict de TypeScript ralentit-il une équipe ?

Il ralentit les premiers jours, le temps de traiter les erreurs révélées par le compilateur. Ensuite il accélère les livraisons : les erreurs sont détectées à la compilation, pas signalées par les utilisateurs en production.

Les Server Components imposent-ils d'abandonner le Pages Router ?

Non. Le Pages Router reste supporté par Next.js et les deux routeurs coexistent dans un même projet. La migration se décide route par route, en commençant par les pages à fort trafic qui bénéficient du rendu serveur.

Comment détecter ces erreurs avant la mise en production ?

Par la configuration, pas par la vigilance : règles ESLint react-hooks en niveau erreur, typecheck bloquant en CI, analyse du bundle par route et revue de code sur les frontières de données. Une erreur détectée en CI coûte quelques minutes ; la même erreur en production coûte un incident.

Sources

  1. https://react.dev/learn/you-might-not-need-an-effect
  2. https://nextjs.org/docs/app/guides/caching
  3. https://www.typescriptlang.org/tsconfig/#strict

Un projet, une reprise, une équipe à constituer ?

Parlons-en 30 minutes : nous cadrons votre besoin et vous repartez avec une recommandation argumentée — que vous travailliez avec nous ou non.

Démarrer la conversation
Tous les articles