React 17 делегирует события к root вместо document
React выполняет делегирование событий автоматически с момента своего первого выпуска. Непосредственно к узлу document он прикрепляет по одному обработчику для каждого типа событий.
Хоть это и улучшает производительность приложения, сообщается о многих проблемах из-за делегирования событий на узле document.
Чтобы продемонстрировать одну из проблем, давай рассмотрим пример.
В приведенном ниже примере мы взяли простой компонент React, который выводит в лог событие при нажатии на кнопку Click и отображается в div с идентификатором react-root. Контейнер React DOM завернут в div с id main, у которого есть событие change, содержащее stopPropagation().
// Div событие change содержит stopPropagation()
<div id="main">
// Div где реакт компонент будет отображен
<div id="react-root"></div>
</div>function App() {
const handleClick = (e) => {
console.log(e);
};
return (
<div className="App">
<h1>Example</h1>
<button onClick={handleClick}>Click</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('react-root'));Присоединение события change к div#main
document.getElementById("main").addEventListener(
"change",
function (e) {
e.stopPropagation();
},
false
);Когда нажимаем на кнопку - мы не видим события в консоле.
Причиной такого неожиданного поведения является раскрывающееся событие onChange, которое прикреплено к узлу document. Событие change тега div#main, содержащее e.stopPropagation(), предотвращает раскрывающееся событие onChange.
Чтобы исправить такие проблемы, React 17 больше не подключает обработчики событий на уровне document. Вместо этого он прикрепляет их к корневому контейнеру DOM, в котором отображается дерево React.
Изменения в React 17
После изменений в React 17 события прикрепляются к корневому контейнеру DOM, в котором отображается дерево React. В нашем примере событие будет прикреплено к div с идентификатором react-root. Поэтому наше событие будет инициировано, когда будет нажата кнопка.
Заметка
Релиз-кандидат React 17 можно установить отсюда.
Ознакомьcя с предыдущим обсуждением делегирования событий здесь и pull request здесь.