Règles de lint de React 19 dans ESLint 10 lorsque eslint-plugin-react est en retard
Pourquoi eslint-plugin-react ne fonctionne plus avec ESLint 10, comment une configuration axée sur Biome limite le linting de React à 11 règles, et comment intégrer cette version modifiée dans une configuration plate ainsi que dans Next.js.
Mettre à jour une base de code React vers ESLint 10 se heurte souvent à une seule dépendance : eslint-plugin-react. À l’heure où cet article est écrit, sa dernière version ne prend pas en charge ESLint 10, et la correction correspondante n’a pas encore été intégrée. Cet article explique cette impossibilité, décrit comment une branche indépendante, @ternaus/eslint-plugin-react, a réduit l’ensemble des règles aux vérifications essentielles pour React 19, désormais assurées en grande partie par Biome, et montre comment l’installer dans une configuration simple ainsi que dans Next.js.
Pourquoi les règles de linting sont plus importantes lorsque des agents écrivent du code
Plus une équipe confie de travail aux agents de codage, plus ses exigences relatives au répertoire doivent être exécutables. La vérification manuelle est un moyen coûteux pour détecter des erreurs prévisibles. Les hooks pré-commit, les tests, les vérifications de conventions déterministes et des commits courts soumis à révision transforment ces exigences en signaux de réussite/échec sur lesquels l’agent peut agir, tout en maintenant chaque échec suffisamment mineur pour être diagnostiqué. Le linting fait partie de ces mécanismes de contrôle ; c’est pourquoi la perte de la couche de linting React lors d’une mise à niveau de l’outilchain représente bien plus qu’un simple inconvénient.
Qu’est-ce qui ne fonctionne plus avec ESLint 10
Parmi les changements majeurs apportés dans la version ESLint 10 figure la suppression des méthodes depuis longtemps dépréciées de l’objet contexte des règles. La dernière version publiée du plugin React, eslint-plugin-react@7.37.5, indique ESLint 9 comme sa version compatible maximale, et certaines de ses règles continuent d’appeler ces méthodes. Avec ESLint 10, cela provoque une erreur du type suivante :
TypeError: contextOrFilename.getFilename is not a function
La méthode en question, context.getFilename(), a été remplacée par la propriété context.filename dans l’API moderne des règles, ce qui oblige à modifier le code du plugin ; aucune option de configuration ne permet de la rétablir.
Upstream suit la trace du problème dans une demande GitHub déposée le 7 février 2026 ; une solution provisoire est arrivée sous forme de demande de fusion le 30 juillet. Aucune des deux n’avait été clôturée à la fin août 2026. Vérifiez leur statut avant d’agir : si Upstream a déjà intégré la prise en charge d’ESLint 10 au moment où vous lisez ceci, la solution la plus simple pourrait être de mettre à jour le plugin d’origine.
Le fork décrit ici vise une matrice de compatibilité spécifique :
- React 19 et versions ultérieures
- ESLint 10 et versions ultérieures, uniquement avec configuration plate
- Biome 2.5.8 et versions ultérieures
- Node.js 22.13, 24 et 26
La configuration basée sur Biome présumée par ce fork
Le choix des règles n’a de sens que par rapport à un stack spécifique. Biome est le formatteur et linter principal, couvrant les vérifications générales pour JavaScript, TypeScript, JSX, DOM ainsi que la plupart des cas liés à React. ESLint reste intégré au flux de travail uniquement pour ce que Biome ne fournit pas : des plugins de framework et quelques contrats spécifiques à React 19.
Les projets de référence fonctionnent avec :
- React 19 sur Next.js 16, écrit en TypeScript
- Biome configuré avec le préreglage
all - ESLint 10 utilisant une configuration plate
- Yarn 4 en tant que gestionnaire de paquets
- Node.js 22, 24 et 26
Dans ce cadre, on ne souhaite pas un autre linter qui chevaucherait les fonctions existantes. On veut uniquement les vérifications spécifiques à React qui ajoutent des informations après l’exécution de Biome.
De 102 règles actives à 11
Ce fork part du repository d’origine et conserve son historique Git, sa licence MIT ainsi que les crédits correspondants ; il est maintenu de manière indépendante à partir de là. Lors du commit où il a bifurqué, le repository d’origine a exporté 104 modules de règles. Le préreglage all en a activé 102 (les deux autres étant obsolètes), tandis que le préreglage recommended a listé 22 règles, parmi lesquelles react/no-unsafe a été explicitement désactivée, ne laissant que 21 règles en vigueur.
Transférer tout cela aurait rendu le package volumineux sans lui donner de but clair. Au lieu de cela, chaque règle a été classée selon le type de décision qu’elle impose :
- Si Biome rapporte déjà le même diagnostic, la règle est supprimée.
- Si elle concerne le formatage, la nommage, la structure des fichiers ou les politiques d’équipe, elle relève de Biome ou de la configuration propre à l’application.
.eslintrc, des solutions de contournement pour le parseur ou des API obsolètes de React, elle ne fait pas partie du contrat de React 19.Douze règles exactement ont été classées dans la première catégorie, dont jsx-key, no-danger, no-unknown-property et self-closing-comp. Un document de correspondance dans le dossier docs du fork associe chacune d’elles à son équivalent Biome.
Les règles qui définissent des styles ou des politiques, telles que prefer-stateless-function, jsx-sort-props ou function-component-definition, ont été supprimées car elles ne concernent pas la conformité avec React 19. no-unused-prop-types et no-unused-state ont également été retirés, car une vérification AST sur un seul fichier ne peut pas répondre de manière fiable à des questions portant sur l’ensemble du projet ; ces règles gênantes incitent les développeurs et les outils à ignorer les résultats de linting. Tous les autres éléments exclus étaient des codes de compatibilité obsolètes hors de la matrice de support indiquée.
Seulement quatre identifiants de règles provenant des sources ont été conservés : no-deprecated, no-invalid-html-attribute, no-direct-mutation-state et jsx-no-constructed-context-values.
Nouvelles règles, et une qui a été délibérément supprimée
Trois propositions provenant des sources non intégrées étaient pertinentes pour la transition vers React 19 :
- Détection des composants qui affichent
undefined(problème en amont n°3020) - Interdiction de l’utilisation de
defaultPropssur les composants fonctionnels (problème n°3911) - Préférence pour un initialisateur différé pour
useState(PR n°3579)
Tous ces éléments ont été mis en œuvre, puis la règle no-render-return-undefined a été supprimée à nouveau. React 19 autorise un composant à retourner undefined, donc l’interdire reviendrait à imposer un style interne sous couvert d’une règle du framework. Les deux autres règles ont été intégrées sous les noms de no-function-default-props, qui signale une API ignorée par React 19 sur les composants fonctionnels, et prefer-use-state-lazy-initialization, une alerte concernant des opérations inutiles effectuées à chaque rendu, comme l’utilisation de expensive() au lieu de () => expensive().
Cinq autres règles ciblent des comportements spécifiques de React 19, qu’ils soient nouveaux ou renforcés par rapport aux versions précédentes : no-prop-types, no-misspelled-lifecycle-methods, jsx-no-key-after-spread, controlled-form-requires-handler et no-implicit-ref-callback-return. La règle concernant les appels de référence est un bon exemple de l’importance de cela aujourd’hui : puisque React 19 permet à un appel de référence de retourner une fonction de nettoyage, une fonction flèche qui retourne implicitement une valeur n’est plus inoffensive.
Ainsi, la version 8.0.0 intègre 11 règles, toutes classées recommended. Les neuf règles de correction correspondent à des erreurs ; les deux règles relatives aux performances sont des avertissements. Un préreglage all dupliquerait soit recommended, soit ne différerait que par le degré de gravité, c’est pourquoi le package n’en propose pas un.
Quels projets réels ont été détectés par des tests qui ne l’ont pas fait
Dès la version 8.0.0-rc.3, les tests unitaires et les vérifications de paquets ont été réussis. C’est lors de l’installation du plugin dans des applications réelles que les erreurs utiles ont commencé à apparaître.
La première catégorie concernait les métadonnées des attributs HTML. La règle no-invalid-html-attribute rejetait des attributs parfaitement valides, tels que alt, accept, name, loading, form et value sur <select>, <option> et <textarea>. Corriger ce problème a nécessité trois cycles de traitement des problèmes et de propositions de modification dans le suivi du fork (#21/#22, #25/#26 et #29/#31). La solution définitive a consisté à considérer les attributs de contenu HTML WHATWG et les propriétés du DOM React comme deux sources d’information distinctes, plutôt que de supposer qu’une seule table de métadonnées les décrivait tous deux.
La deuxième panne provenait de Next.js. eslint-config-next@16 génère une configuration plate, mais il lit les règles depuis le champ de forme ancienne react.configs.recommended.rules. La branche forkée n’a exposé que react.configs.flat.recommended, ce qui a provoqué des problèmes de configuration avant même que ne soit analysé un seul fichier. Une modification ultérieure (problème n°24, PR n°27) a ajouté ce champ en mode lecture seule, sans réintroduire la prise en charge de .eslintrc. Comme Next.js importe le plugin sous son nom non scellé, une résolution via Yarn est également nécessaire, comme indiqué ci-dessous.
Ces intégrations ont donné naissance aux versions candidates 4 à 6 et ont redéfini la stratégie de test. Avant la version finale, le fichier tarball npm compressé est analysé avec publint, importé par des tests écrits en ESM, CommonJS et TypeScript, et exécuté selon les paramètres de configuration prétendument supportés par le paquet, avec des tests d’intégration sur Node.js 22.13, 24 et 26. Cette leçon s’applique à tout paquet d’outils : testez l’artefact que vous publiez, en utilisant les consommateurs que vous prenez en charge, et non seulement l’arborescence source.
Le paquet résultant est nativement en ESM, ne fait usage que de flat-config, et conserve l’espace de noms des règles familier react/*.
Installation et configuration
Les commandes utilisent Yarn 4. Ajoutez d’abord Biome, ESLint 10 ainsi que le plugin en tant que dépendances de développement :
yarn add --dev @biomejs/biome@'>=2.5.8' eslint@^10 @ternaus/eslint-plugin-react@^8.0.0
Activez l’ensemble complet des règles stables de Biome ainsi que son domaine React dans biome.json, afin que Biome couvre tout ce que la branche originale a intentionnellement omis :
{
"linter": {
"domains": {
"react": "all"
},
"rules": {
"preset": "all"
}
}
}
Ensuite, ajoutez les règles React restantes dans eslint.config.js. L’opération de spread fusionne l’enregistrement des plugins et les règles du préréglage dans un objet de configuration délimité par le glob files :
import react from '@ternaus/eslint-plugin-react';
export default [
{
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
...react.configs.flat.recommended,
},
];
Si ce glob inclut des fichiers .ts ou .tsx, enregistrez un analyseur compatible TypeScript dans un objet de configuration antérieur ; le préréglage ne configure pas automatiquement d’analyseur pour cela.
Exécutez les deux outils en parallèle, généralement comme des étapes CI distinctes ou dans un seul script :
yarn biome check .
yarn eslint .
Les identifiants des règles conservent le préfixe react, de sorte que les modifications apportées au plugin original s’appliquent également aux règles qui existent encore :
{
rules: {
'react/no-deprecated': 'error',
'react/no-implicit-ref-callback-return': 'error',
},
}
L’intégration dans Next.js
eslint-config-next importe le plugin sous le nom de eslint-plugin-react. Avec Yarn, vous pouvez rediriger ce nom vers la branche forkée via resolutions:
{
"devDependencies": {
"@ternaus/eslint-plugin-react": "8.0.0"
},
"resolutions": {
"eslint-plugin-react": "npm:@ternaus/eslint-plugin-react@8.0.0"
}
}
Assurez-vous que les deux numéros de version soient synchronisés. La résolution empêche eslint-config-next d’installer la version originale réservée à ESLint 9 à côté de la branche forkée pour ESLint 10. Comme Next.js enregistre le plugin sous react, les identifiants de règles existants react/* continuent de fonctionner.
Lorsque cette branche forkée n’est pas la bonne option
- Elle ne comprend pas toutes les règles provenant de la version originale. Les configurations qui dépendent de
react/prop-types,react/display-nameoureact/jsx-sort-propsdoivent comparer la liste des règles prises en charge par la branche forkée dans son répertoire avant de procéder au changement.
key.Points clés
- L’erreur ESLint 10 provient de l’élimination des API contextuelles des règles, donc seule une nouvelle version du plugin peut la résoudre.
- Une stack axée sur Biome nécessite bien moins de règles ESLint pour React ; trier les règles en fonction du type de décision qu’elles imposent est une méthode réutilisable pour simplifier toute configuration de linting redondante.
- Les règles qui exigent des preuves à l’échelle de tout le projet génèrent du bruit dans un outil de linting par fichier et il vaut mieux les supprimer plutôt que de les tolérer.
- Test des outils publiés tels que les utilisateurs les voient : l’archive compressée, tous les formats de modules, ainsi que des configurations réelles de framework comme
eslint-config-next. - Avec Next.js, un alias
resolutionsde Yarn permet à la branche forkée de remplacer le paquet non scanné sans modifier les IDs des règles.
Les notes de source et de version se trouvent dans le répertoire du fork.