React 19 Lint-Regeln in ESLint 10 – wenn eslint-plugin-react hinterherhinkt
Warum eslint-plugin-react bei ESLint 10 nicht mehr funktioniert, wie eine Biome-first-Einrichtung die React-Linting-Regeln auf 11 beschränkt und wie man den Fork in flat config sowie Next.js integrieren kann.
Beim Aufrüsten einer React-Codebasis auf ESLint 10 stößt man oft an einer einzigen Abhängigkeit fest: eslint-plugin-react. Zum Zeitpunkt der Erstellung unterstützt die neueste Version dieses Plugins nicht ESLint 10, und die entsprechende Korrektur im Hauptprojekt wartet noch auf Integration. Dieser Artikel erläutert das Problem, zeigt, wie eine unabhängige Fork namens @ternaus/eslint-plugin-react das Regelwerk auf die für React 19 noch relevanten Überprüfungen reduziert, da Biome nun den größten Teil der Linting-Arbeit übernimmt, und erklärt außerdem, wie man dieses Plugin in einer einfachen Konfiguration sowie in Next.js installiert.
Warum Lint-Regeln bei automatischem Code-Schreiben wichtiger sind
Höre ein Team mehr Aufgaben an Code-Agenten aus, desto mehr der Anforderungen an sein Repository müssen ausführbar sein. Eine manuelle Überprüfung ist teuer, wenn es darum geht, vorhersehbare Fehler aufzudecken. Pre-Commit-Hooks, Tests, deterministische Konventionenprüfungen sowie kleine, überprüfbare Commit-Vorgänge verwandeln diese Anforderungen in Erfolg/Ablehnungs-Signale, auf die Agenten reagieren können, und sorgen dafür, dass jeder Fehler klein genug ist, um diagnostiziert zu werden. Linting gehört zu diesen Schutzmaßnahmen – deshalb ist das Verlieren der React-Lint-Ebene bei einem Toolchain-Upgrade mehr als nur ein Ärgernis.
Was bricht unter ESLint 10?
Zu den grundlegenden Änderungen in der ESLint 10-Version gehört die Entfernung von seit langer Zeit deaktivierten Methoden im Objekt des Regelkontexts. Die neueste veröffentlichte Version des React-Plugins, eslint-plugin-react@7.37.5, listet ESLint 9 als höchst unterstützte Version auf, und einige seiner Regeln rufen weiterhin diese Methoden auf. Unter ESLint 10 führt dies zu einem Absturz wie diesem:
TypeError: contextOrFilename.getFilename is not a function
Die betreffende Methode, context.getFilename(), wurde in der modernen Regel-API durch die Eigenschaft context.filename ersetzt, weshalb sich der Plugin-Code ändern muss; kein Konfigurationsflag kann sie wiederherstellen.
Upstream verfolgt das Problem in einem GitHub-Issue vom 7. Februar 2026; ein möglicher Fix wurde am 30. Juli als Pull Request eingereicht. Beides war Ende August 2026 noch nicht abgeschlossen. Überprüfen Sie den Status, bevor Sie handeln: Falls Upstream bis zu dem Zeitpunkt, an dem Sie dies lesen, die ESLint-10-Unterstützung bereits bereitgestellt hat, könnte der einfachste Weg darin bestehen, das ursprüngliche Plugin zu aktualisieren.
Der hier beschriebene Fork zielt auf eine bestimmte Unterstützungsmatrix ab:
- React 19 und neuer
- ESLint 10 und neuer, nur flache Konfiguration
- Biome 2.5.8 und neuer
- Node.js 22.13, 24 und 26
Die auf Biome ausgerichtete Einrichtung, die dieser Fork voraussetzt
Die Auswahl der Regeln macht nur dann Sinn, wenn sie auf einem bestimmten Stack angewendet werden. Biome ist der primäre Formatierer und Linter und deckt allgemeine JavaScript-, TypeScript-, JSX-, DOM- sowie die meisten React-Prüfungen ab. ESLint bleibt nur dann Teil des Toolchains, wenn Biome etwas nicht bietet: Framework-Plugins sowie einige React 19-Spezifikationen.
Die Referenzprojekte laufen unter:
- React 19 auf Next.js 16, geschrieben in TypeScript
- Biome konfiguriert mit dem
all-Voreinstellung - ESLint 10 mit flacher Konfiguration
- Yarn 4 als Paketmanager
- Node.js 22, 24 und 26
In dieser Anordnung möchte man keinen zweiten, überschneidenden Linter. Man benötigt nur die speziell für React vorgesehenen Prüfungen, die zusätzliche Informationen liefern, nachdem Biome bereits ausgeführt wurde.
Von 102 aktiven Regeln auf 11
Die Fork beginnt im upstream-Repository und behält dessen Git-Geschichte, MIT-Lizenz sowie die Notierung der Quelle bei; sie wird unabhängig davon gepflegt. Bei dem Commit, an dem sie abgezweigt wurde, exportierte upstream 104 Regelmodule. Die Voreinstellung all aktivierte 102 davon (die anderen beiden waren veraltet), und recommended listete 22 Regeln auf, wobei react/no-unsafe ausdrücklich deaktiviert wurde, sodass 21 Regeln weiterhin gelten.
Hätte man alles übernommen, wäre das Paket weiterhin groß geblieben, ohne dass es einen klaren Zweck gehabt hätte. Stattdessen wurden die einzelnen Regeln nach der Art der Entscheidung sortiert, die sie durchsetzen:
- Falls Biome bereits denselben Diagnosewert meldet, wird die Regel weggelassen.
- Falls es um Formatierung, Benennung, Dateistruktur oder Teamrichtlinien geht, gehört die Regel zu Biome oder zur eigenen Konfiguration der Anwendung.
.eslintrc-Konfigurationen, Workarounds für den Parser oder veraltete React-APIs existiert, fällt sie außerhalb des Contracts von React 19.Genaue 20 Regeln fielen in die erste Kategorie, darunter jsx-key, no-danger, no-unknown-property und self-closing-comp. Ein Zuordnungsdocument im Docs-Ordner des Forks verknüpft jede dieser Regeln mit ihrem entsprechenden Äquivalent in Biome.
Regeln, die Style oder Richtlinien kodieren, wie zum Beispiel prefer-stateless-function, jsx-sort-props oder function-component-definition, wurden entfernt, da sie nichts über die Konformität mit React 19 aussagen. no-unused-prop-types und no-unused-state fielen weg, weil eine Prüfung des ASTs in einer einzigen Datei keine zuverlässige Antwort auf eine Frage liefern kann, die das gesamte Projekt betrifft; störende Regeln bringen Menschen und Agenten dazu, die Lint-Ausgaben zu ignorieren. Alles andere, was ausgeschlossen wurde, waren Codeelemente für Legacy-Kompatibilität, die nicht zur angegebenen Support-Matrix gehören.
Nur vier upstream-Regel-IDs blieben erhalten: no-deprecated, no-invalid-html-attribute, no-direct-mutation-state und jsx-no-constructed-context-values.
Neuere Regeln sowie eine absichtlich entfernte Regel
Drei noch nicht integrierte upstream-Vorschläge waren für den Umstieg auf React 19 relevant:
- Flaggs für Komponenten, die
undefinedausgeben (Upstream-Problem #3020) - Ausschließung von
defaultPropsbei Funktionskomponenten (Problem #3911) - Vorzug einer verzögerten Initialisierung für
useState(PR #3579)
Sämtliche drei Punkte wurden umgesetzt, anschließend wurde no-render-return-undefined wieder entfernt. React 19 erlaubt es einer Komponente, undefined zurückzugeben; daher wäre ein Verbot lediglich ein interner Stil, der als Framework-Regel getarnt ist. Die anderen beiden wurden als no-function-default-props implementiert, welches eine API kennzeichnet, die React 19 bei Funktionskomponenten ignoriert, sowie als prefer-use-state-lazy-initialization, ein Warnhinweis vor überflüssigen Aufwänden bei jeder Renderung, wie zum Beispiel dem Übergabe von expensive() anstelle von () => expensive().
Fünf weitere Regeln beziehen sich auf spezifisches Verhalten von React 19 – sei es neu hinzugekommen oder aus früheren Versionen verschärft: no-prop-types, no-misspelled-lifecycle-methods, jsx-no-key-after-spread, controlled-form-requires-handler und no-implicit-ref-callback-return. Die Regel zu den Ref-Callbacks ist ein gutes Beispiel dafür, warum das jetzt wichtig ist: Da React 19 es erlaubt, dass ein Ref-Callback eine Aufräumfunktion zurückgibt, ist eine Pfeilfunktion, die implizit einen Wert aus einem Ref-Callback zurückgibt, nicht mehr harmlos.
Daher enthält Version 8.0.0 insgesamt 11 Regeln, alle mit der Einstufung recommended. Die neun Korrektheitsregeln gelten als Fehler, die beiden Leistungsregeln als Warnungen. Ein Voreinstellungen-Wert all würde entweder recommended duplizieren oder sich nur in der Schwere unterscheiden, weshalb das Paket keinen solchen Wert anbietet.
Welche echten Projekte etwas entdeckten, was die Tests nicht taten
Bis 8.0.0-rc.3 haben die Einheitstests sowie die Paketprüfungen erfolgreich bestanden. Erst bei der Installation des Plugins in echten Anwendungen traten nützliche Fehler auf.
Die erste Problemkategorie betraf Metadaten zu HTML-Attributen. no-invalid-html-attribute lehnte völlig gültige Attribute ab, darunter alt, accept, name, loading, form sowie value in <select>, <option> und <textarea>. Um dies zu beheben, waren drei Runden mit Tickets und Pull Requests im Tracker des Forks erforderlich (#21/#22, #25/#26 und #29/#31). Die dauerhafte Lösung bestand darin, WHATWG-HTML-Inhaltsattribute und React-DOM-Eigenschaften als zwei getrennte Quellen der Wahrheit zu betrachten, anstatt anzunehmen, dass eine einzige Metadaten-Tabelle beides beschreibt.
Der zweite Fehler stammte von Next.js. eslint-config-next@16 erzeugt eine flache Konfiguration, liest jedoch die Regeln aus dem im alten Stil gehaltenen Feld react.configs.recommended.rules. Die Fork stellte lediglich react.configs.flat.recommended zur Verfügung, wodurch die Konfiguration bereits vor der Überprüfung einer einzigen Datei fehlschlug. Eine nachfolgende Änderung (Issue #24, PR #27) fügte dieses Feld nur zum Lesen hinzu, ohne die Unterstützung für .eslintrc wieder einzuführen. Da Next.js den Plugin unter seinem unbeschränkten Namen importiert, ist auch eine Yarn-Resolution erforderlich, wie unten gezeigt.
Diese Integrationen führten zu den Release-Kandidaten 4 bis 6 und veränderten die Teststrategie. Vor der endgültigen Veröffentlichung wird das komprimierte npm-Tarball mit publint überprüft, von in ESM, CommonJS und TypeScript geschriebenen Testkonsumenten importiert und mit der von Next.js vorgegebenen Konfiguration geprüft, wobei CI auf Node.js 22.13, 24 und 26 genutzt wird. Die Lektion gilt für jedes Tooling-Paket: Testen Sie das von Ihnen veröffentlichte Artefakt unter Berücksichtigung der von Ihnen unterstützten Konsumenten – nicht nur den Quellcodebaum.
Das resultierende Paket ist natives ESM, verwendet ausschließlich flat-config und behält den bekannten Regelnamensraum react/* bei.
Installation und Konfiguration
Die Befehle verwenden Yarn 4. Fügen Sie zunächst Biome, ESLint 10 sowie das Plugin als Entwicklungskomponenten hinzu:
yarn add --dev @biomejs/biome@'>=2.5.8' eslint@^10 @ternaus/eslint-plugin-react@^8.0.0
Aktivieren Sie in biome.json die vollständige stabile Regelmenge von Biome sowie dessen React-Bereich, damit Biome alles abdeckt, was die Fork absichtlich weggelassen hat:
{
"linter": {
"domains": {
"react": "all"
},
"rules": {
"preset": "all"
}
}
}
Fügen Sie anschließend die verbleibenden React-Regeln zu eslint.config.js hinzu. Die Spread-Operation fügt die Plugin-Registrierungen und Regeln des Presets zu einem Konfigurationsobjekt zusammen, das durch den files-Glob begrenzt wird:
import react from '@ternaus/eslint-plugin-react';
export default [
{
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
...react.configs.flat.recommended,
},
];
Falls dieser Glob Dateien mit den Endungen .ts oder .tsx enthält, registrieren Sie einen für TypeScript geeigneten Parser in einem früheren Konfigurationsobjekt; das Preset stellt keinen solchen Parser bereit.
Führen Sie die beiden Tools nebeneinander aus, typischerweise als separate CI-Schritte oder in einem einzigen Skript:
yarn biome check .
yarn eslint .
Die Regel-IDs behalten das Präfix react bei, sodass Überschreibungen, die für das ursprüngliche Plugin geschrieben wurden, auch auf die weiterhin vorhandenen Regeln angewendet werden:
{
rules: {
'react/no-deprecated': 'error',
'react/no-implicit-ref-callback-return': 'error',
},
}
Integration in Next.js
eslint-config-next importiert das Plugin als eslint-plugin-react. Mit Yarn kann man diesen Namen über resolutions auf die Fork umleiten:
{
"devDependencies": {
"@ternaus/eslint-plugin-react": "8.0.0"
},
"resolutions": {
"eslint-plugin-react": "npm:@ternaus/eslint-plugin-react@8.0.0"
}
}
Achten Sie darauf, dass die beiden Versionen im Einklang sind. Die Lösung verhindert, dass eslint-config-next die ursprüngliche ESLint 9-Version neben der Fork für ESLint 10 herunterlädt. Da Next.js das Plugin unter react registriert, funktionieren die bestehenden react/*-Regel-IDs weiterhin.
Wann diese Fork die falsche Wahl ist
- Sie enthält nicht alle Regeln aus der Quelldatei. Konfigurationen, die auf
react/prop-types,react/display-nameoderreact/jsx-sort-propsangewiesen sind, sollten vor dem Umstieg die Liste der unterstützten Regeln in der Repository-Datei der Fork überprüfen.
key-Eigenschaften.Haupterkenntnisse
- Der Absturz von ESLint 10 resultiert aus entfernten rule-context-APIs, weshalb nur eine Plugin-Veröffentlichung dies behebt.
- Eine auf Biome ausgerichtete Architektur benötigt deutlich weniger ESLint-React-Regeln; die Klassifizierung der Regeln nach dem Art der von ihnen durchgesetzten Entscheidungen ist eine wiederverwendbare Methode, um überschneidende Lint-Einstellungen zu reduzieren.
- Regeln, die Beweise für das gesamte Projekt erfordern, erzeugen Unruhe in einem Dateiweisen Linter und sollten lieber entfernt werden, anstatt hingenommen zu werden.
- Getestete Tools aus Sicht der Nutzer: das komprimierte Archiv, alle Moduleformate sowie echte Framework-Konfigurationen wie
eslint-config-next. - Mit Next.js ermöglicht ein Yarn
resolutions-Alias es, dass die Fork anstelle des unscoped-Pakets verwendet wird, ohne die Regel-IDs ändern zu müssen.
Die Quellcode- und Veröffentlichungsnotizen befinden sich im Repository der Fork.