Зачем нужно всегда импортировать React в scope модуля?
Основы React
Это правило из «старого мира»: до React 17 любой файл с JSX обязан был иметь import React from 'react' — иначе скомпилированный код падал. Сегодня правило устарело.
Причина исторического правила
JSX — не JavaScript; компилятор (Babel/TS) превращал его в вызовы React.createElement:
const badge = <span className="badge">7</span>;
// ↓ компиляция (старый трансформ)
const badge = React.createElement('span', { className: 'badge' }, '7');В скомпилированном коде появляется идентификатор React. Если его нет в области видимости модуля — ReferenceError: React is not defined в рантайме, хотя в исходнике «React вроде не используется». Отсюда требование импортировать React в scope каждого JSX-модуля (и ESLint-правило react/react-in-jsx-scope).
Что изменилось (React 17+, 2020)
Новый JSX-трансформ: компилятор сам импортирует служебную функцию из jsx-runtime:
import { jsx as _jsx } from 'react/jsx-runtime'; // вставляется автоматически
const badge = _jsx('span', { className: 'badge', children: '7' });Ручной импорт для JSX стал не нужен; правило react/react-in-jsx-scope в конфигурациях отключают. Требуется настройка компилятора: "jsx": "react-jsx" в tsconfig или соответствующий пресет Babel — в современных шаблонах (Vite, Next.js) это по умолчанию.
Когда импорт всё же нужен
Только для явного использования API: import { useState, memo } from 'react', классовые компоненты, типы (React.ReactNode). Сам по себе JSX импорта больше не требует.
Коротко для собеседования
Раньше JSX компилировался в React.createElement — идентификатор React должен был быть в scope каждого JSX-файла, иначе ReferenceError. С React 17 новый трансформ автоматически импортирует jsx-runtime, и import React нужен только для явного API (хуки, классы, типы).