В чем разница работы Event в React и в DOM?
Основы React
React оборачивает нативные события в собственную систему — SyntheticEvent с делегированием. Отличия от «чистого» DOM важны при интеграциях и отладке.
Как события устроены в React
- Делегирование: React не вешает слушатель на каждый элемент — один набор обработчиков стоит на корневом контейнере приложения (с React 17; раньше — на document). Событие всплывает до корня, React определяет целевой компонент и запускает ваши обработчики.
- SyntheticEvent — кросс-браузерная обёртка над нативным событием: одинаковые свойства/поведение во всех браузерах; оригинал доступен через
e.nativeEvent. - camelCase-пропсы:
onClick,onMouseEnterвместо атрибутов; передаётся функция, а не строка.
Практические отличия
- Имена и поведение: onChange в React срабатывает на каждый ввод (как нативный input), onFocus/onBlur реализованы через focusin/focusout (всплывают).
- Фазы: перехват — суффикс Capture (
onClickCapture). - Порядок с нативными слушателями: нативный addEventListener на элементе сработает раньше React-обработчика (событие ещё должно доплыть до корня) — источник сюрпризов при интеграции с внешними библиотеками.
- stopPropagation: остановка в React-обработчике не остановит нативные слушатели, уже отработавшие ниже; и наоборот — нативный stopPropagation до корня «выключит» React-обработчик.
- Порталы: события всплывают по React-дереву, а не по DOM — клик в портале дойдёт до React-родителя, хотя в DOM они не вложены.
- До React 17 существовал event pooling (переиспользование объектов события) — удалён.
Что не изменилось
Семантика та же: preventDefault/stopPropagation работают, target/currentTarget на месте; для нестандартных случаев всегда можно взять addEventListener через ref.
Коротко для собеседования
React использует SyntheticEvent и делегирование на корень приложения: кросс-браузерность, camelCase-обработчики, всплытие по React-дереву (включая порталы). Отличия от DOM: порядок срабатывания с нативными слушателями, поведение stopPropagation на границе двух систем, onChange «на каждый ввод». Нативный event — в e.nativeEvent.