Skip to main content

React Event Object Properties: Complete Guide

Every event handler in React receives a SyntheticEvent object as its first argument—a goldmine of information about what the user just did. Understanding the event object's key properties like event.target, event.target.value, and event.stopPropagation() lets you build flexible form handlers, read input values, and control how events flow through your component tree.

Key Takeaways

  • Every React event handler receives a SyntheticEvent object (usually named e) containing information about the user's interaction
  • event.target references the DOM element that triggered the event (the input the user typed in, the button they clicked)
  • event.target.value reads the current value from an input or textarea; event.target.checked reads a checkbox's state
  • The "one handler for multiple inputs" pattern using event.target.name and a single handleChange function eliminates repetitive code in large forms
  • event.stopPropagation() prevents an event from bubbling up to parent elements, essential for nested clickable components

The Event Object: Core Concept

When a user interacts with an element (clicking, typing, hovering), React passes your event handler a SyntheticEvent object. This object wraps the browser's native event and provides a consistent API across all browsers, eliminating cross-browser compatibility issues.

The most useful property on the event object is target: the DOM element where the event originated. If a user clicks a button, event.target is that button. If they type in an input, event.target is that input.

function MyButton() {
function handleClick(e) {
console.log(e); // The SyntheticEvent object
console.log(e.target); // The <button> DOM element
}

return <button onClick={handleClick}>Click Me</button>;
}

Reading Input Values with event.target.value

The most common use case for the event object is capturing what a user typed into an input field. Here's the fundamental pattern:

import React, { useState } from 'react';

export default function NameForm() {
const [name, setName] = useState('');

function handleChange(e) {
const newValue = e.target.value;
setName(newValue);
}

return (
<>
<label>Name: </label>
<input value={name} onChange={handleChange} />
<p>Your name is: {name}</p>
</>
);
}

How it works:

  1. User types into the input
  2. onChange event fires, calling handleChange(e)
  3. e.target is the input element; e.target.value is what the user typed
  4. setName() updates state with the new value
  5. Component re-renders; the input now shows the updated value

This pattern—where state controls the input's value—is called a controlled component. React is the single source of truth for the input's current value, allowing you to validate, format, or modify the input before storing it.

Advanced Pattern: One Handler for Multiple Inputs

With many form fields, writing a separate handler for each becomes repetitive:

// Repetitive approach (don't do this)
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');

const handleFirstNameChange = (e) => setFirstName(e.target.value);
const handleLastNameChange = (e) => setLastName(e.target.value);
const handleEmailChange = (e) => setEmail(e.target.value);

Instead, combine all form data into one state object and use a single generic handler:

import React, { useState } from 'react';

export default function SignupForm() {
const [formState, setFormState] = useState({
firstName: '',
lastName: '',
email: '',
});

function handleChange(e) {
const { name, value } = e.target;

setFormState(prevState => ({
...prevState,
[name]: value
}));
}

return (
<form>
<input
name="firstName"
value={formState.firstName}
onChange={handleChange}
placeholder="First Name"
/>
<input
name="lastName"
value={formState.lastName}
onChange={handleChange}
placeholder="Last Name"
/>
<input
name="email"
value={formState.email}
onChange={handleChange}
placeholder="Email"
/>
</form>
);
}

How it works:

  1. All form data lives in one formState object
  2. Each input has a name attribute matching its corresponding state property (firstName, lastName, email)
  3. All inputs call the same handleChange handler
  4. Inside the handler, destructure name and value from the event target
  5. Use computed property syntax [name]: value to update the correct state field

This pattern reduces boilerplate dramatically. The handler works for any number of inputs without modification.

Handling Checkboxes

For checkboxes, use event.target.checked instead of event.target.value:

const [formState, setFormState] = useState({
email: '',
agreeToTerms: false,
});

function handleChange(e) {
const { name, type, value, checked } = e.target;
const newValue = type === 'checkbox' ? checked : value;

setFormState(prevState => ({
...prevState,
[name]: newValue
}));
}

return (
<>
<input name="email" type="text" value={formState.email} onChange={handleChange} />
<input
name="agreeToTerms"
type="checkbox"
checked={formState.agreeToTerms}
onChange={handleChange}
/>
</>
);

The handler now checks type === 'checkbox' and uses checked for checkboxes, value for text inputs.

Controlling Event Propagation

Events in React (like the browser) bubble up from child elements to parents. When you click a button inside a div, both the button's onClick and the div's onClick fire.

Use event.stopPropagation() to stop an event from reaching parent elements:

function ChildButton({ onClick }) {
function handleClick(e) {
e.stopPropagation(); // Stop bubbling to parent
onClick();
}

return <button onClick={handleClick}>Click Me</button>;
}

function Parent() {
return (
<div onClick={() => alert('Parent div clicked!')}>
<ChildButton onClick={() => alert('Child button clicked!')} />
</div>
);
}

When you click the button, only "Child button clicked!" appears. The stopPropagation() call prevents the click event from ever reaching the parent div's onClick handler.

Essential Event Object Properties

Here are the most important properties and methods on a SyntheticEvent:

Property/MethodUse CaseExample
event.targetReference to the element that triggered the eventconst input = e.target;
event.target.valueRead text input or textarea valueconst text = e.target.value;
event.target.checkedRead checkbox or radio button stateconst isChecked = e.target.checked;
event.target.nameRead the name attribute (for form handling)const fieldName = e.target.name;
event.preventDefault()Prevent default behavior (e.g., form submission)e.preventDefault();
event.stopPropagation()Stop event bubbling to parent elementse.stopPropagation();
event.typeString describing the event typeevent.type === 'click'

Example: Complete Form with Validation

Here's a realistic form that demonstrates all concepts:

import React, { useState } from 'react';

export default function UserForm() {
const [formState, setFormState] = useState({
username: '',
password: '',
rememberMe: false,
});

const [errors, setErrors] = useState({});

function handleChange(e) {
const { name, type, value, checked } = e.target;
const newValue = type === 'checkbox' ? checked : value;

setFormState(prevState => ({
...prevState,
[name]: newValue
}));

// Clear error for this field when user starts correcting it
if (errors[name]) {
setErrors(prev => ({
...prev,
[name]: ''
}));
}
}

function handleSubmit(e) {
e.preventDefault(); // Stop form from refreshing page

const newErrors = {};
if (formState.username.length === 0) newErrors.username = 'Username required';
if (formState.password.length === 0) newErrors.password = 'Password required';

if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}

console.log('Form submitted:', formState);
}

return (
<form onSubmit={handleSubmit}>
<div>
<input
name="username"
type="text"
value={formState.username}
onChange={handleChange}
placeholder="Username"
/>
{errors.username && <span style={{ color: 'red' }}>{errors.username}</span>}
</div>

<div>
<input
name="password"
type="password"
value={formState.password}
onChange={handleChange}
placeholder="Password"
/>
{errors.password && <span style={{ color: 'red' }}>{errors.password}</span>}
</div>

<label>
<input
name="rememberMe"
type="checkbox"
checked={formState.rememberMe}
onChange={handleChange}
/>
Remember me
</label>

<button type="submit">Login</button>
</form>
);
}

This form demonstrates: one state object, one handler for all inputs, validation on submit, and e.preventDefault() to stop the page from refreshing.

Frequently Asked Questions

What is the difference between SyntheticEvent and a native browser event?

React wraps browser events in a SyntheticEvent object for consistency. This means the same code works across all browsers—IE, Chrome, Firefox—without worrying about browser-specific quirks. React handles the cross-browser differences behind the scenes. For 99% of cases, you don't notice the difference; the API is identical.

Can I access the event object asynchronously after the handler finishes?

No. React reuses SyntheticEvent objects for performance reasons. After your handler completes, the event object is recycled and its properties become null. If you need to access event properties asynchronously, copy them to variables first:

function handleChange(e) {
const value = e.target.value; // Copy to variable
setTimeout(() => console.log(value), 1000); // Use the variable, not e
}

When should I use event.preventDefault()?

Call preventDefault() on events whose default browser behavior you want to block. Common cases: form submission (to handle it with JavaScript), link clicks (to handle with React Router), and keyboard events. Without it, a form will refresh the page on submit.

Why does my checkbox not update when I click it?

Make sure you're using checked={formState.fieldName} for checkboxes, not value. Also ensure your handler checks type === 'checkbox' and reads the checked property. For a text input, use value; for checkboxes/radio buttons, use checked.

Can I stop event propagation conditionally?

Yes. For example, only stop propagation if the user meets a condition:

function handleClick(e) {
if (userHasPermission) {
e.stopPropagation();
}
onClick();
}

Further Reading

Deepen your understanding of React events and form handling:


Glossary

SyntheticEvent: React's cross-browser wrapper around the native browser event object, providing a consistent API.

event.target: Property referring to the DOM element that dispatched the event (the input typed in, button clicked, etc.).

Controlled Component: A form input whose value is controlled by React state, making React the single source of truth.

Event Propagation (Bubbling): Process where an event travels from a target element up through its parent elements in the DOM tree.

Computed Property Name: JavaScript syntax [variableName]: value that uses a variable's content as an object property key.

preventDefault(): Event method that stops the browser's default action for an event (e.g., form submission refreshing the page).