September 29, 2020
React has been doing
event delegation
automatically since its first release.
It attaches one handler per event type directly at the document
node.
Though it improves the performance of an application,
many
issues
have been
reported
due to the event delegation on the document
node.
To demonstrate one of the issues let's take an example of a select dropdown.
CountryDropDown
in the below example is a React component for country selection,
which would be rendered to a div with id react-root
.
The react DOM container is wrapped inside a div with id main
that has a change
event containing stopPropagation()
.
<!--Div's change event contains stopPropagation()-->
<div id="main">
<!--Div where react component will be rendered -->
<div id="react-root"></div>
</div>
class CountryDropDown extends React.Component {
state = {
country: '',
}
const handleChange = e => {
this.setState({ country: e.target.value });
}
render() {
return (
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Country</th>
<th>Selected country</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select value={this.state.country}
onChange={this.handleChange}
>
<option value="">--Select--</option>
<option value="India">India</option>
<option value="US">US</option>
<option value="Dubai">Dubai</option>
</select>
</td>
<td>
{this.state.country}
</td>
</tr>
</tbody>
</table>
);
}
}
ReactDOM.render(<CountryDropDown />, document.getElementById('react-root'));
Attaching change event to the main div
document.getElementById("main").addEventListener(
"change",
function (e) {
e.stopPropagation();
},
false
);
When a country is selected, we cannot see the selected country. Watch this video
to see it in action.
The reason for this unexpected behavior is the onChange
event of dropdown
which is attached to the document
node.
The change
event of the main
div containing e.stopPropagation()
prevents
the onChange
event of dropdown.
To fix such issues, React 17 no longer attaches event handlers at the document level. Instead, it attaches them to the root DOM container into which React tree is rendered.
Image is taken from React 17 blog.
After changes in React 17, events are attached to the root DOM container into which the React tree is rendered.
In our example, onChange
event of dropdown would be attached to the div with id react-root
.
This event would be triggered when any country is selected rendering the expected behavior.
React 17 release candidate can be installed from here.
Check out the earlier discussion on event delegation here and the pull request here.
If this blog was helpful, check out our full blog archive.