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 здесь.