SyntheticEvent Explained
What SyntheticEvent Provides
Every event handler in React receives a SyntheticEvent object instead of the raw browser event. It behaves consistently across browsers and includes the same familiar methods and properties you'd expect, like .target and .preventDefault().
Note: You rarely need to think about SyntheticEvent explicitly -- just use it the same way you'd use a normal DOM event.
Warning: In React versions before 17, SyntheticEvent objects were pooled and reused, so accessing them asynchronously required extra care -- this was removed in React 17+.
Example: What SyntheticEvent Provides
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function ClickLogger() {
function handleClick(event) {
console.log("Event type:", event.type);
}
return <button onClick={handleClick}>Click and check console</button>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<ClickLogger />);
</script>
</body>
</html>
Preventing Default Behavior
Calling event.preventDefault() on a SyntheticEvent stops the browser's default action for that event, like a form submitting and reloading the page, or a link navigating away. This works exactly like it does with native DOM events.
Note: Always call preventDefault() on form submit handlers if you're managing the submission yourself with JavaScript.
Warning: Forgetting preventDefault() on a form's submit handler causes the page to reload, wiping out any React state.
Example: Preventing Default Behavior
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function Form() {
function handleSubmit(event) {
event.preventDefault();
alert("Form submitted without reloading the page!");
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<Form />);
</script>
</body>
</html>
Accessing event.target
event.target refers to the actual DOM element that triggered the event, giving you access to its properties like value for an input field. This is the most common way to read what a user typed or selected.
Note: For text inputs, event.target.value is the standard way to read the current typed value inside an onChange handler.
Warning: For checkboxes, you need event.target.checked instead of event.target.value to get the correct boolean state.
Example: Accessing event.target
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function NameInput() {
const [name, setName] = React.useState("");
return (
<div>
<input onChange={(e) => setName(e.target.value)} placeholder="Type your name" />
<p>You typed: {name}</p>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<NameInput />);
</script>
</body>
</html>
- Assuming SyntheticEvent has fewer features than the native event -- it wraps almost everything the native event provides.
- Storing the event object for use later after the handler has finished, in older React versions (this was pooled and reused).
- Confusing SyntheticEvent method names with native DOM event methods, which are mostly the same but worth double-checking.
- React wraps native browser events in a cross-browser SyntheticEvent object.
- SyntheticEvent provides consistent behavior across different browsers.
- Common methods like
.preventDefault()and.stopPropagation()work as expected. - You access the underlying native event via
event.nativeEventif ever needed.
Consistent behavior across all modern browsers is exactly the purpose of SyntheticEvent; event pooling was removed in React 17+, simplifying async event access.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: