React's SyntheticEvent: One Wrapper for All Browsers

React's SyntheticEvent is a browser-agnostic wrapper around native events, ensuring your onClick handlers behave identically everywhere. The main footgun: event objects are pooled for performance, so you can't access their properties in an async callback.
Why it exists
Browsers have minor but frustrating inconsistencies in their event system implementations. For example, property names might differ between browsers for the same event. React abstracts away these differences to provide a stable, cross-browser API for developers.
The mental model
Think of SyntheticEvent as a diplomatic translator. A native browser event speaks a specific dialect (e.g., an old Safari click event). The SyntheticEvent translator takes that dialect and converts it into a universal language that your React component understands, guaranteeing properties like e.target and e.preventDefault() work the same everywhere.
How it works
React uses event delegation. Instead of attaching a listener to every DOM node with an onClick, it attaches a single listener for each event type at the document root. When an event fires, React's listener identifies the component, creates or retrieves a pooled SyntheticEvent object that wraps the native event, and then calls your handler. After your handler executes, the SyntheticEvent object is released back to a pool to be reused, which improves performance by reducing garbage collection.
When to use it
You use it implicitly every time you write an event handler in React, like onKeyDown, onFocus, or onClick. The first argument your handler function receives is always a SyntheticEvent instance.
When not to use it
If you need the raw browser event, perhaps for a third-party library that expects it, you can access it via the nativeEvent property on the synthetic event object (e.g., e.nativeEvent). This is an escape hatch and rarely needed.
One canonical example
The most common footgun is accessing an event asynchronously. Consider function handleChange(e) { setTimeout(() => { console.log(e.target.value); }, 100); }. This will fail because by the time the timeout runs, the event e has been recycled. To fix this, either extract the data you need before the async call (const value = e.target.value;) or call e.persist() to tell React not to recycle that specific event object.
Interview question
What is the primary reason accessing 'e.target.value' inside an asynchronous callback (e.g., setTimeout) often fails with React's SyntheticEvent?
- a.The 'e.target' property is not guaranteed to exist after the initial event handler completes.
- b.React's event delegation system detaches the 'e.target' reference once the event bubbles up.
- c.Native browser events are not designed to be accessed across synchronous and asynchronous boundaries.
- d.React reuses the SyntheticEvent object from a pool, clearing its properties before the async callback runs.Correct
Why? this is the answer
The card explicitly states that 'by the time the timeout runs, the event e has been recycled' due to React's event pooling for performance. Option B is incorrect because event delegation concerns where listeners are attached, not the persistence of event object properties.
Just read this? Test yourself on what you have been reading.
Read the original → react.dev
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on react — each one lists the topics its interview covers.
See open roles