Zasady lintingu React 19 w ESLint 10, gdy eslint-plugin-react jest w tyle
Dlaczego eslint-plugin-react przestaje działać w ESLint 10, jak ustawienie oparte na Biome ogranicza sprawdzanie kodu w React do 11 reguł oraz jak integrować tę wersję z konfiguracją typu flat i Next.js.
Wdrożenie aktualizacji bazy kodu React do wersji ESLint 10 często zatrzymuje się z powodu jednej zależności: eslint-plugin-react. W chwili pisania tego tekstu jego najnowsza wersja nie obsługuje ESLint 10, a poprawka w głównym repozytorium wciąż czeka na połączenie. Ten artykuł wyjaśnia przyczynę tego problemu, pokazuje, w jaki sposób niezależny fork @ternaus/eslint-plugin-react skrócił zbiór reguł do tych właściwych dla React 19, które są nadal istotne, gdy Biome zajmuje się większością kontroli jakości kodu, oraz pokazuje, jak zainstalować go w prostym konfiguratorze flat oraz w Next.js.
Dlaczego reguły kontroli jakości są ważniejsze, gdy kod piszą automatyczne narzędzia
Im więcej pracy zespół przekazuje agentom do kodowania, tym większa część jego wymagań dotyczących repozytorium musi być wykonywalna. Ludzka weryfikacja to drogie rozwiązanie, jeśli chodzi o wykrywanie błędów typowych. Hooki przed zatwierdzeniem zmian, testy, deterministyczne sprawdzanie konwencji oraz małe, podlegające weryfikacji komitety przekształcają te wymagania w sygnały „przejdzie/nie przejdzie”, na których agent może się oprzeć, a także sprawiają, że każda awaria jest na tyle mała, by można ją zdiagnozować. Linting to jeden z takich mechanizmów ochronnych, dlatego utrata warstwy lintingu React podczas aktualizacji narzędzi jest czymś znacznie więcej niż tylko niedogodnością.
Co przestaje działać w ESLint 10
Wśród istotnych zmian w wersji ESLint 10 znajduje się usunięcie metod dawno zdeprecjonowanych z obiektu kontekstu reguł. Najnowsza opublikowana wersja pluginu dla React, eslint-plugin-react@7.37.5, wskazuje ESLint 9 jako najwyższą wspieraną wersję, a niektóre z jego reguł nadal korzystają z tych metod. W ESLint 10 powoduje to awarię w takim wyglądzie:
TypeError: contextOrFilename.getFilename is not a function
Omawiana metoda, context.getFilename(), została zastąpiona właściwością context.filename w nowoczesnej API reguł, dlatego kod pluginu musi ulec zmianie; żaden flaga konfiguracyjna nie może jej przywrócić.
Upstream śledzi ten problem w zgłoszeniu na GitHubie z dnia 7 lutego 2026 roku; propozycja naprawy trafiła jako pull request 30 lipca. Do późna sierpnia 2026 roku żadne z tych zgłoszeń nie zostało zamkniętych. Sprawdź ich status przed podjęciem działań: jeśli do chwili czytania tego tekstu Upstream wprowadzi już wsparcie dla ESLint 10, najprostszym rozwiązaniem może być aktualizacja oryginalnego pluginu.
Fork opisany tutaj jest skierowany do konkretnej matrycy wsparcia:
- React 19 i nowsze
- ESLint 10 i nowsze, tylko konfiguracja typu flat
- Biome 2.5.8 i nowsze
- Node.js 22.13, 24 i 26
Ustawienie oparte na Biome, które zakłada ten fork
Wybór reguł ma sens tylko w kontekście określonego środowiska. Biome jest głównym narzędziem do formatowania i sprawdzania kodu, obejmującym ogólne zasady dotyczące JavaScript, TypeScript, JSX, DOM oraz większość sprawdzeń specyficznych dla React. ESLint pozostaje w tym zestawie narzędzi wyłącznie tam, gdzie Biome nie zapewnia odpowiednich funkcji: plugini do frameworków oraz kilka specyficznych dla React 19 kontraktów.
Projekty referencyjne działają w następujący sposób:
- React 19 na Next.js 16, napisany w TypeScript
- Biome skonfigurowane z użyciem presetu
all - ESLint 10 z konfiguracją typu flat
- Yarn 4 jako menedżer pakietów
- Node.js 22, 24 i 26
W takim układzie nie chce się mieć drugiego, nakładającego się narzędzia do sprawdzania kodu. Potrzebne są jedynie specyficzne dla React sprawdzenia, które dodają dodatkowe informacje po uruchomieniu Biome.
Od 102 aktywnych reguł do 11
Następca pochodzi z repozytorium upstream i zachowuje swoją historię Git, licencję MIT oraz informacje o źródle; jest utrzymywany niezależnie od niego. W komitcie, w którym powstała gałąź, upstream wyeksportował 104 moduły reguł. Ustawienie all włączyło 102 z nich (dwa pozostałe zostały uznane za przestarzałe), a recommended wymieniło 22 reguły, z których react/no-unsafe zostało wyraźnie wyłączone, pozostawiając 21 w mocy.
Przeniesienie wszystkiego sprawiłoby, że pakiet pozostałby duży bez jasnego celu. Zamiast tego każda reguła została posortowana według rodzaju decyzji, którą egzekwuje:
- Jeśli Biome już raportuje ten sam wynik diagnostyczny, reguła jest pomijana.
- Jeśli dotyczy formatowania, nazewnictwa, struktury plików lub zasad zespołu, należy do Biome lub do własnych ustawień aplikacji.
.eslintrc, rozwiązań workaround dla parsera lub przestarzałych API React, wykracza poza zasady React 19.Dokładnie 20 reguł trafiło do pierwszej kategorii, w tym jsx-key, no-danger, no-unknown-property oraz self-closing-comp. Dokument mapujący w folderze docs forka łączy każdą z nich z jej odpowiednikiem w Biome.
Zasady określające styl lub politykę, takie jak prefer-stateless-function, jsx-sort-props czy function-component-definition, zostały usunięte, ponieważ nie mówią nic o poprawności kodu w React 19. no-unused-prop-types oraz no-unused-state również zniknęły, gdyż sprawdzenie AST w jednym pliku nie może wiarygodnie odpowiedzieć na pytania dotyczące całego projektu; takie zasady skłaniają ludzi i narzędzia do ignorowania wyników sprawdzania kodu. Wszystkie pozostałe wykluczone elementy to kod zapewniający kompatybilność z starszymi wersjami, który nie mieści się w określonej macierzy wsparcia.
Tylko cztery identyfikatory zasad z źródła przetrwały: no-deprecated, no-invalid-html-attribute, no-direct-mutation-state oraz jsx-no-constructed-context-values.
Nowe zasady oraz jedna celowo usunięta
Trzy niepołączone propozycje z źródła były istotne przy przejściu na React 19:
- komponenty flagowe, które wyświetlają wartość
undefined(problem w górnej części łańcucha #3020) - Zabranienie użycia
defaultPropsw komponentach funkcyjnych (problem #3911) - Nadanie pierwszeństwa opóźnionej inicjalizacji dla
useState(PR #3579)
Wszystkie trzy rozwiązania zostały zaimplementowane, a następnie ponownie usunięto opcję no-render-return-undefined. React 19 pozwala komponentowi zwracać wartość undefined, więc jej zakazanie byłoby jedynie własną zasadą maskowaną jako reguła frameworka. Pozostałe dwa rozwiązania zostały włączone jako no-function-default-props, które sygnalizuje użycie API ignorowanego przez React 19 w komponentach funkcyjnych, oraz prefer-use-state-lazy-initialization, które jest ostrzeżeniem dotyczącym zbędnego obliczania na każdym renderowaniu, np. przy użyciu expensive() zamiast () => expensive().
Pięć dodatkowych zasad dotyczy konkretnych zachowań React 19, zarówno nowych, jak i uściślonych w porównaniu z wcześniejszymi wersjami: no-prop-types, no-misspelled-lifecycle-methods, jsx-no-key-after-spread, controlled-form-requires-handler oraz no-implicit-ref-callback-return. Zasada dotycząca ref-callback jest dobrym przykładem tego, dlaczego to ma teraz znaczenie: ponieważ React 19 pozwala funkcji callback do ref zwracać funkcję czyszczenia, funkcja strzałkowa, która domyślnie zwraca wartość z takiej funkcji, nie jest już nieszkodliwa.
Wersja 8.0.0 zawiera zatem 11 zasad, wszystkie o statusie recommended. Dziewięć zasad dotyczących poprawności to błędy, a dwie zasady dotyczące wydajności to ostrzeżenia. Ustawienie all albo powtórzyłoby zasady recommended, albo różniłoby się jedynie stopniem powagi, dlatego pakiet nie oferuje takiego ustawienia.
Jakie rzeczywiste projekty wykryły to, czego nie zdołały testy
W wersji 8.0.0-rc.3 testy jednostkowe oraz sprawdzenia pakietów zakończyły się pomyślnie. Dopiero podczas instalacji wtyczki w rzeczywistych aplikacjach zaczęły pojawiać się przydatne błędy.
Pierwszą kwestią były metadane atrybutów HTML. Funkcja no-invalid-html-attribute odrzucała w pełni poprawne atrybuty, takie jak alt, accept, name, loading, form oraz value używane w elementach <select>, <option> i <textarea>. Ustalenie właściwego rozwiązania wymagało trzech rund korekty błędów i zgłoszeń w systemie trackingu forku (#21/#22, #25/#26 i #29/#31). Ostatecznym rozwiązaniem było traktowanie atrybutów treści HTML według standardu WHATWG oraz właściwości React DOM jako dwóch odrębnych źródeł prawdy, zamiast zakładania, że jedna tabela metadanych opisuje oba.
Drugi problem pojawił się w Next.js. eslint-config-next@16 tworzy prostą konfigurację, ale czyta zasady z pola o tradycyjnej strukturze react.configs.recommended.rules. Fork udostępnił jedynie react.configs.flat.recommended, więc konfiguracja zawiodła jeszcze przed sprawdzeniem choćby jednego pliku. Kolejna zmiana (issue #24, PR #27) dodała to pole wyłącznie do odczytu, bez przywracania obsługi plików .eslintrc. Ponieważ Next.js importuje ten plugin pod jego nieoznaczonym nazwą, konieczne jest również rozwiązanie problemu z Yarnem, co pokazano poniżej.
Te integracje doprowadziły do powstania wersji kandydujących 4–6 oraz zmieniły strategię testowania. Przed ostateczną publikacją spakowany plik tarball npm jest sprawdzany za pomocą publint, importowany przez narzędzia testowe napisane w formacie ESM, CommonJS i TypeScript, a także przetwarzany zgodnie z konfiguracją Next.js, którą pakiet deklaruje jako wspieraną, przy użyciu CI na Node.js 22.13, 24 i 26. Ta zasada odnosi się do każdego pakietu narzędziowego: należy testować artefakt, który publikuje się, w kontekście narzędzi, które są przez niego obsługiwane, a nie tylko drzewo źródłowe.
Otrzymany pakiet jest w pełni zgodny z formatem ESM, wykorzystuje tylko konfigurację typu flat-config i zachowuje znajomy przestrzeń nazw reguł react/*.
Instalacja i konfiguracja
Polecenia wymagają Yarn 4. Najpierw należy dodać Biome, ESLint 10 oraz odpowiedni plugin jako zależności typu dev:
yarn add --dev @biomejs/biome@'>=2.5.8' eslint@^10 @ternaus/eslint-plugin-react@^8.0.0
Włącz pełny, stabilny zestaw reguł Biome oraz jego domenę React w pliku biome.json, aby Biome obejmował wszystko, co celowo pominięto w wersji forkowanej:
{
"linter": {
"domains": {
"react": "all"
},
"rules": {
"preset": "all"
}
}
}
Następnie dodaj pozostałe reguły React do pliku eslint.config.js. Operacja spread łączy rejestrację pluginów i reguł z presetu w jeden obiekt konfiguracyjny, ograniczony do plików określonych przez wyrażenie globowe files:
import react from '@ternaus/eslint-plugin-react';
export default [
{
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
...react.configs.flat.recommended,
},
];
Jeśli to wyrażenie globowe obejmuje pliki .ts lub .tsx, zarejestruj parser obsługujący TypeScript we wcześniejszym obiekcie konfiguracyjnym; preset nie konfiguruje takiego parsera automatycznie.
Zrób to dwa narzędzia równocześnie, zazwyczaj jako oddzielne kroki w procesie CI lub w jednym skrypcie:
yarn biome check .
yarn eslint .
ID reguł zachowują przedrostek react, więc modyfikacje zapisane dla oryginalnego pluginu są stosowane również do reguł, które nadal istnieją:
{
rules: {
'react/no-deprecated': 'error',
'react/no-implicit-ref-callback-return': 'error',
},
}
Integracja z Next.js
eslint-config-next importuje ten plugin jako eslint-plugin-react. Za pomocą Yarn można skierować to nazwanie na fork poprzez resolutions:
{
"devDependencies": {
"@ternaus/eslint-plugin-react": "8.0.0"
},
"resolutions": {
"eslint-plugin-react": "npm:@ternaus/eslint-plugin-react@8.0.0"
}
}
Należy utrzymywać obie liczby wersji w zgodzie. Dzięki temu rozwiązaniu eslint-config-next nie ładuje oryginalnej wersji dostępnej tylko dla ESLint 9 obok forka dla ESLint 10. Ponieważ Next.js rejestruje ten plugin pod nazwą react, istniejące identyfikatory reguł typu react/* nadal funkcjonują.
Kiedy ten fork jest niewłaściwym wyborem
- Nie zawiera on wszystkich reguł z oryginału. Konfiguracje, które polegają na
react/prop-types,react/display-namelubreact/jsx-sort-props, powinny sprawdzić listę reguł obsługiwanych przez fork w jego repozytorium przed dokonaniem zmiany.
key.Główne wnioski
- Awaria ESLint 10 wynika z usunięcia API kontekstu reguł, więc tylko nowa wersja pluginu może to naprawić.
- Stack oparty przede wszystkim na Biome wymaga znacznie mniej reguł ESLint React; sortowanie reguł według rodzaju podejmowanych decyzji to metoda, którą można wykorzystać wielokrotnie do usunięcia zbędnych elementów w konfiguracji lintingu.
- Reguły, które wymagają dowodów z całego projektu, tworzą zbędny hałas w narzędziu lintingu dla pojedynczych plików i lepiej je usunąć, niż tolerować.
- Test narzędzi dostępnych dla użytkowników: spakowany archiwum, każdy format modułu oraz rzeczywiste konfiguracje frameworków, takie jak
eslint-config-next. - Dzięki Next.js alias Yarn
resolutionsumożliwia użycie forku zamiast pakietu bez zakresu, bez konieczności zmiany identyfikatorów reguł.
Zapisy źródłowe i notatki o wydaniu znajdują się w repozytorium forku.