Главная / Статьи / Правила проверки React 19 в ESLint 10 при отставании eslint-plugin-react

Правила проверки React 19 в ESLint 10 при отставании eslint-plugin-react

Почему eslint-plugin-react перестаёт работать в ESLint 10, как настройка с упором на Biome ограничивает проверку кода в React 11 правилами, и как интегрировать эту версию в flat config и Next.js.

1826 слов

Повышение версии кодбазы на React до ESLint 10 часто останавливается из-за одной зависимости: eslint-plugin-react. На момент написания статьи его последняя версия не поддерживает ESLint 10, а исправление в исходном проекте все еще ожидает интеграции. В этой статье объясняется причина сбоев, показано, как независимый форк @ternaus/eslint-plugin-react сократил набор правил до тех, которые важны для React 19 после того, как Biome начал выполнять большую часть проверок, а также рассказано, как установить его в обычной конфигурации и в Next.js.

Почему правила линтинга становятся важнее, когда код пишут автоматизированные агенты

Чем больше работы команда передаёт агентам для кодирования, тем больше требований к её репозиторию должно быть выполнимыми. Проверка вручную — дорогостоящий способ обнаружения предсказуемых ошибок. Хуки перед коммитом, тесты, проверки согласно определённым правилам и небольшие коммиты, подлежащие ревью, превращают эти требования в сигналы «успех/неудача», на которые может отреагировать агент, а также позволяют сделать каждую неудачу достаточно мелкой для диагностики. Linting — один из таких инструментов контроля, поэтому потеря слоя проверки React при обновлении инструментальной сборки — это не просто неудобство.

Что ломается при переходе на ESLint 10

Среди кардинальных изменений в версии ESLint 10 — удаление давно заброшенных методов из объекта контекста правил. В новейшей опубликованной версии плагина для React, eslint-plugin-react@7.37.5, как минимальная поддерживаемая версия указан ESLint 9, однако некоторые из правил в этом плагине по-прежнему используют эти методы. При работе с ESLint 10 это приводит к подобным сбоям:

TypeError: contextOrFilename.getFilename is not a function

Рассматриваемый метод context.getFilename() был заменён свойством context.filename в современном API правил, поэтому код плагина требует изменений; никакой флаг конфигурации не может восстановить прежнюю версию метода.

Upstream отслеживает проблему в задаче GitHub, зарегистрированной 7 февраля 2026 года; кандидатский решение появилось в виде pull request 30 июля. Ни одна из них на момент конца августа 2026 года не была закрыта. Проверьте их статус перед действием: если к моменту прочтения этого текста upstream уже выпустил поддержку ESLint 10, самым простым решением может стать обновление оригинального плагина.

Описанный здесь форк ориентирован на определённую матрицу поддержки:

  • React 19 и новее
  • ESLint 10 и новее, только flat config
  • Biome 2.5.8 и новее
  • Node.js 22.13, 24 и 26

Подход, основанный на Biome, который предполагается в этом форке

Выбор правил имеет смысл только в контексте конкретной стек-технологии. Biome является основным инструментом форматирования и проверки кода, обрабатывая общие вопросы, связанные с JavaScript, TypeScript, JSX, DOM и большинством проверок для React. ESLint остается частью инструментария лишь для тех функций, которые не предоставляет Biome: плагины для фреймворков и несколько спецификаций React 19.

В качестве примера используются следующие проекты:

  • React 19 на Next.js 16, написанный на TypeScript
  • Biome с настройкой по предустановке all
  • ESLint 10 с использованием простой конфигурации
  • Yarn 4 в качестве менеджера пакетов
  • Node.js 22, 24 и 26

В такой схеме не нужен дополнительный инструмент проверки кода, который бы дублировал функции первого. Необходимы только специфичные для React проверки, которые могут дать дополнительную информацию после работы Biome.

От 102 активных правил до 11

Эта версия берётся из исходного репозитория и сохраняет его историю Git, лицензию MIT и указание авторства; она поддерживается независимо от него. На этапе создания ветки исходный репозиторий экспортировал 104 модуля правил. Предустановка all включала 102 из них (два других были устаревшими), а параметр recommended перечислял 22 правила, из которых react/no-unsafe был явно отключён, в результате чего действовали 21 правило.

Перенос всего содержимого привёл бы к тому, что пакет остался бы большим без чёткой цели. Вместо этого каждое правило было отсортировано по типу принимаемого им решения:

  • Если Biome уже сообщает об одинаковой проблеме, такое правило игнорируется.
  • Если речь идёт о форматировании, названиях, структуре файлов или правилах команды, то такое правило относится к Biome или к собственной конфигурации приложения.
  • Если речь идет о общей гипертекстуре, требующей доказательств в масштабах проекта или учитывающей типы, она исключается, вместо того чтобы приводить к неопределенным результатам.
  • Если такая гипертекстура существует для React 18, устаревших конфигураций .eslintrc, обходных решений для парсера или устаревших API React, она не входит в спецификации React 19.
  • Если она позволяет выявлять проблемы с корректностью в React 19 или предоставляет полезные предупреждения об эффективности, связанные с React, она сохраняется или подвергается реализации.
  • Ровно 20 правил попали в первую категорию, включая jsx-key, no-danger, no-unknown-property и self-closing-comp. В документации форка в папке docs имеется таблица соответствий, связывающая каждое из этих правил с его аналогом в Biome.

    Правила, определяющие стиль или политику, такие как prefer-stateless-function, jsx-sort-props или function-component-definition, были исключены, поскольку они не имеют отношения к соответствию стандартам React 19. Правила no-unused-prop-types и no-unused-state были удалены, так как проверка AST в одном файле не может надёжно ответить на вопросы, касающиеся всего проекта; чрезмерно активные правила заставляют разработчиков и автоматизированные инструменты игнорировать результаты проверки. Все остальные исключённые элементы представляли собой код для обеспечения совместимости с устаревшими версиями, не входящий в указанную матрицу поддержки.

    Прошли проверку лишь четыре идентификатора правил из исходного кода: no-deprecated, no-invalid-html-attribute, no-direct-mutation-state и jsx-no-constructed-context-values.

    Новые правила и одно правило, которое было намеренно удалено

    Три предложения из исходного кода, которые не были объединены, имели отношение к переходу на React 19:

    • флаги компонентов, возвращающих значение undefined (проблема на этапе разработки #3020)
    • запрет на использование defaultProps в функциональных компонентах (проблема #3911)
    • предпочтение ленивой инициализации для useState (PR #3579)

    Все три решения были реализованы, после чего опция no-render-return-undefined снова была удалена. React 19 позволяет компонентам возвращать значение undefined, поэтому его запрет был бы лишь собственным стилем разработки, маскирующимся под правило фреймворка. Два остальных решения были включены как no-function-default-props, который фиксирует использование API, которое React 19 игнорирует в функциональных компонентах, и prefer-use-state-lazy-initialization — предупреждение о ненужных действиях при каждой отрисовке, таких как передача функции expensive() вместо () => expensive().

    Ещё пять правил касаются конкретного поведения React 19 — будь то нововведения или ужесточения по сравнению с предыдущими версиями: no-prop-types, no-misspelled-lifecycle-methods, jsx-no-key-after-spread, controlled-form-requires-handler и no-implicit-ref-callback-return. Правило, касающееся возврата значения из функции-обратного вызова ref, является хорошим примером того, почему это сейчас важно: поскольку React 19 позволяет функции-обратному вызову ref возвращать функцию для очистки, стрелочная функция, которая косвенно возвращает значение из такой функции, больше не считается безопасной.

    Поэтому версия 8.0.0 включает 11 правил, все из которых отнесены к категории recommended. Девять правил, связанных с корректностью, обозначают ошибки; два правила, связанных с производительностью, — предупреждения. Предустановка all либо дублировала бы категорию recommended, либо отличалась бы только по степени серьёзности, поэтому в пакете она не предоставляется.

    Что обнаружили реальные проекты, чего не смогли выявить тесты

    К версии 8.0.0-rc.3 тесты на единицы и проверки пакетов прошли успешно. Именно при установке плагина в реальные приложения начались полезные сбои.

    Первой проблемой стали метаданные атрибутов HTML. Функция no-invalid-html-attribute отклоняла совершенно корректные атрибуты, включая alt, accept, name, loading, form и value для элементов <select>, <option> и <textarea>. Чтобы решить эту проблему, потребовалось три раунда обсуждения проблем и патчей в трекере форка (#21/#22, #25/#26 и #29/#31). Постоянным решением стало рассмотрение атрибутов содержимого HTML от WHATWG и свойств React DOM как двух отдельных источников информации, вместо предположения, что одна таблица метаданных описывает оба.

    Вторая проблема возникла в Next.js. eslint-config-next@16 генерирует флэт-конфигурацию, но при этом читает правила из поля react.configs.recommended.rules устаревшего формата. В форке было предоставлено только поле react.configs.flat.recommended, поэтому конфигурация сломалась ещё до того, как был проанализирован хотя бы один файл. В последующих изменениях (issue #24, PR #27) было добавлено это поле исключительно в режиме чтения, без восстановления поддержки файла .eslintrc. Поскольку Next.js импортирует плагин по его нескоупедному имени, требуется также решение проблемы с подключением через Yarn, что показано ниже.

    Благодаря этим интеграциям были созданы кандидаты на выпуск 4–6, а также изменилась стратегия тестирования. Перед окончательным выпуском сжатый архив npm проверяется с помощью publint, импортируется тестовыми приложениями, написанными на ESM, CommonJS и TypeScript, а также проходит обработку согласно настройкам Next.js, которые заявлено поддерживаются пакетом; тестирование выполняется в среде CI на Node.js 22.13, 24 и 26. Этот принцип применим к любому инструментальному пакету: необходимо тестировать сам продукт, который вы публикуете, с учётом приложений-использователей, которые он поддерживает, а не только исходный код.

    Результатом становится пакет в формате ESM, использующий только flat-config, при этом сохраняется знакомое пространство имен правил react/*.

    Установка и настройка

    Для выполнения команд требуется Yarn 4. Сначала добавьте Biome, ESLint 10 и соответствующий плагин в качестве dev-зависимостей:

    yarn add --dev @biomejs/biome@'>=2.5.8' eslint@^10 @ternaus/eslint-plugin-react@^8.0.0
    

    Включите полный стабильный набор правил Biome и его сегмент для React в файле biome.json, чтобы Biome покрывал всё, что намеренно было исключено в форке:

    {
      "linter": {
        "domains": {
          "react": "all"
        },
        "rules": {
          "preset": "all"
        }
      }
    }
    

    Затем добавьте оставшиеся правила React в файл eslint.config.js. Операция расширения объединяет регистрацию плагинов и правила предустановки в объект конфигурации, ограниченный параметром files:

    import react from '@ternaus/eslint-plugin-react';
    
    export default [
      {
        files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
        ...react.configs.flat.recommended,
      },
    ];
    

    Если параметр files включает файлы с расширениями .ts или .tsx, зарегистрируйте парсер, поддерживающий TypeScript, в более раннем объекте конфигурации; предустановка не настраивает его автоматически.

    Запускайте оба инструмента одновременно, как правило, в виде отдельных шагов CI или в одном скрипте:

    yarn biome check .
    yarn eslint .
    

    Идентификаторы правил сохраняют префикс react, поэтому переопределения, написанные для исходного плагина, применяются к тем правилам, которые всё ещё существуют:

    {
      rules: {
        'react/no-deprecated': 'error',
        'react/no-implicit-ref-callback-return': 'error',
      },
    }
    

    Интеграция с Next.js

    eslint-config-next импортирует плагин под именем eslint-plugin-react. С помощью Yarn можно перенаправить это имя на форк через параметр resolutions:

    {
      "devDependencies": {
        "@ternaus/eslint-plugin-react": "8.0.0"
      },
      "resolutions": {
        "eslint-plugin-react": "npm:@ternaus/eslint-plugin-react@8.0.0"
      }
    }
    

    Следите за тем, чтобы номера версий совпадали. Благодаря этой настройке eslint-config-next не загружает оригинальную версию ESLint 9 вместе с форком для ESLint 10. Поскольку Next.js регистрирует плагин под именем react, существующие идентификаторы правил вида react/* продолжают работать.

    Когда этот форк — неправильный выбор

    • Он не включает все правила из исходного проекта. Конфигурации, зависящие от react/prop-types, react/display-name или react/jsx-sort-props, должны сравнить список поддерживаемых правил в репозитории форка перед тем, как переключаться на него.
  • Он предполагает, что Biome покрывает всё остальное. Без Biome или эквивалента сокращение до 11 правил приводит к реальным пробелам, таким как отсутствие атрибутов key.
  • Он не предоставляет контракта совместимости с React Native, а его правила DOM анализируют только элементы, которые являются тегами HTML в нижнем регистре.
  • Это независимо поддерживаемый форк. Взвесите это против ожидания поддержки от основного проекта и пересмотрите свой выбор, когда поступит pull request от основного разработчика.
  • Основные выводы

    • Сбой ESLint 10 возникает из-за удаления API контекста правил, поэтому его можно исправить только с помощью новой версии плагина.
    • Стек, основанный на Biome, требует гораздо меньше правил ESLint для React; сортировка правил по типу принимаемых ими решений — это метод, который можно использовать повторно для устранения дублирующихся настроек проверки кода.
    • Правила, которым нужны доказательства из всего проекта, создают лишний шум в инструменте проверки по файлам, и их лучше удалить, чем терпеть.
    • Тестирование инструментов в том виде, в котором их видят пользователи: архив с компрессией, все форматы модулей и реальные конфигурации фреймворков, такие как eslint-config-next.
    • В Next.js алиас Yarn resolutions позволяет использовать форк вместо неограниченного пакета без изменения идентификаторов правил.

    Исходный код и примечания к выпуску находятся в репозитории форка.