---
title: "React 17 delegates events to root instead of document"
description: "React 17 delegates events to root instead of document"
canonical_url: "https://www.bigbinary.com/blog/react-17-delegates-events-to-root-instead-of-document"
markdown_url: "https://www.bigbinary.com/blog/react-17-delegates-events-to-root-instead-of-document.md"
---

# React 17 delegates events to root instead of document

React 17 delegates events to root instead of document

- Author: Chetan Gawai
- Published: September 29, 2020
- Categories: ReactJS

React has been doing [event delegation](https://davidwalsh.name/event-delegate)
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](https://github.com/facebook/react/issues/13451)
[issues](https://github.com/facebook/react/issues/4335)
[have been](https://github.com/facebook/react/pull/8117)
[reported](https://github.com/facebook/react/issues/285#issuecomment-253502585)
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()`.

```html
<!--Div's change event contains stopPropagation()-->
<div id="main">
  <!--Div where react component will be rendered -->
  <div id="react-root"></div>
</div>
```

```javascript

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

```javascript
document.getElementById("main").addEventListener(
  "change",
  function (e) {
    e.stopPropagation();
  },
  false
);
```

When a country is selected, we cannot see the selected country. Watch this video

<iframe
  width="100%"
  height="315"
  src="https://www.youtube.com/embed/6BgfvUz_3JM"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
></iframe>

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.

![event delegation](https://www.bigbinary.com/blog/images/images_used_in_blog/2020/react-17-delegates-events-to-root-instead-of-document/react_17_event_delegation.png)

Image is taken from
[React 17 blog](https://reactjs.org/blog/2020/08/10/react-v17-rc.html).

## Changes in React 17

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.

<iframe
  width="100%"
  height="315"
  src="https://www.youtube.com/embed/6BgfvUz_3JM"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
></iframe>

## Note

React 17 release candidate can be installed from
[here](https://reactjs.org/blog/2020/08/10/react-v17-rc.html#installation).

Check out the earlier discussion on event delegation
[here](https://github.com/facebook/react/issues/13525) and the pull request
[here](https://github.com/facebook/react/pull/18195).

## Links

- [Human page](https://www.bigbinary.com/blog/react-17-delegates-events-to-root-instead-of-document)
