Synthetic Events
Overview
When you interact with a web page (click a button, type in an input), the browser generates a native DOM event object containing data about that interaction (mouse coordinates, the key pressed, etc.). However, different browsers (Chrome, Safari, Firefox, older Internet Explorer) historically implemented these event objects slightly differently, forcing developers to write annoying cross-browser compatibility code.
React solves this by wrapping the native browser event inside a Synthetic Event. A Synthetic Event is a React-specific, cross-browser wrapper. It guarantees that the event object will have the exact same properties and methods regardless of which browser the user is currently using.
When you accept an event (or e) parameter in your onClick or onChange handler, you are receiving this Synthetic Event. It acts exactly like a native event—you can still call e.preventDefault() or e.stopPropagation()—but it completely abstracts away all browser inconsistencies.
Syntax
function SearchInput() {
const handleTyping = (event) => {
// 'event' is the SyntheticEvent object provided by React.
// 'target' is the actual HTML <input> element.
// 'value' is the text currently inside the input.
console.log("User typed:", event.target.value);
};
return <input type="text" onChange={handleTyping} />;
}Common Pitfalls
- Event Pooling (Legacy React 16 issue): In older versions of React (v16 and below), Synthetic Events were 'pooled' to save memory. This meant that once the event handler finished running, all properties on the event object were nullified. If you tried to access
e.target.valueinside an asynchronoussetTimeout, it would crash. React 17 completely removed event pooling, so this is no longer an issue, but you may still encounter old tutorials warning about it.
Interview Questions
A Synthetic Event is a cross-browser wrapper around the browser's native event object. React intercepts native events at the root of the application, wraps them in Synthetic Events to ensure identical behavior across all browsers (Chrome, Safari, Firefox), and then passes them to the component's event handler.
React doesn't actually attach event listeners to every single <button> or <input>. Instead, it attaches one single event listener for every event type at the very root of the application DOM node. When a user clicks a button, the native event bubbles up to the root, React intercepts it, determines which component's onClick prop should be fired, and dispatches the Synthetic Event. This makes React highly memory efficient.
Real-World Example
Handling File Uploads: Even though React uses Synthetic Events, they map 1-to-1 with standard HTML5 features. Accessing e.target.files is exactly how you handle file inputs in vanilla JS, but React guarantees it works smoothly on all browsers.
function FileUploader() {
const handleFileChange = (e) => {
// We dive into the SyntheticEvent to access the native File API
const selectedFile = e.target.files[0];
if (selectedFile) {
console.log(`Preparing to upload: ${selectedFile.name}`);
console.log(`File size: ${selectedFile.size / 1024} KB`);
}
};
return (
<div>
<label>Upload Profile Picture</label>
<input type="file" accept="image/*" onChange={handleFileChange} />
</div>
);
}Check Your Knowledge
Test your understanding of Synthetic Events with these quick questions.