Handling Events in React
Event handling is an important part of web development, as it makes websites interactive. That being said, event handling can be complex, in particular with Javascript, as the event listeners need to be attached to the appropriate nodes. Event handling in React is different, and actually can be argued to increase performance in React applications by the automatic implementation of event delegation and the use of synthetic events.
Essentially, in React, a single event listener is attached to the root of the document and when an event is fired, React is able to map it to the appropriate component element. Furthermore, synthetic events can promote consistency through the normalization of events, thereby ensuring that properties do not differ among browsers and platforms.
While it is beneficial to be able to handle events in a browser-agnostic manner (thanks to the fact that SyntheticEvent is a cross-browser wrapper around the browser’s native event that is passed to event handlers in React), one thing that you have to keep in mind when working with event handlers in React is that event objects are pooled.
Pooling certainly increases performance because objects that an event handler receives can be reused for other events, but this leads to the event object’s properties not being accessible asynchronously because the event’s properties will be reset.
There are two cases in which React’s asynchronicity and event pooling do not play well together:
- Calling on event.target in a setTimeout
- Calling on event.target within setState
Because of the asynchronous nature of setTimeout, writing something like the following would cause an error.
function handleClick(event) {
setTimeout(function () {
console.log(event.target.name);
}, 1000);
}
The most common solution here would be to store the event’s property you are interested in inside its own variable:
function handleClick(event) {
let name = event.target.name;
setTimeout(function () {
console.log(name);
}, 1000);
}
Dealing with event.target within setState also gets tricky, as mentioned above.
Once again, one option would be to “cache” the event, or store it in a variable.
However, we also have the option of using event.persist() to tell React to NOT go ahead with event pooling; in this way, our even object ‘persists’, or remains available to us:
Caching the events works on small to medium scale applications; however, the larger the application, the more difficult it will be to handle numerous variable assignments. In that case, the more appropriate solution would most likely be the use of event.persist().