Passing Arguments to Event Handlers0%

Passing Arguments to Event Handlers

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Passing Arguments to Event Handlers

1. The Challenge of Custom Arguments

When attaching an event listener in React, passing just the function name works when no extra arguments are needed:

JSX
// React automatically passes the SyntheticEvent 'e'
<button onClick={handleClick}>Click</button>

However, in real-world applications, you frequently need to pass custom arguments to your handler—such as an item ID, a user object, or an array index:

JSX
// ❌ WRONG: Executes deleteItem(course.id) immediately on render!
<button onClick={deleteItem(course.id)}>Delete</button>

Writing deleteItem(course.id) invokes the function during render, triggering premature deletions and potentially infinite re-render loops!

2. Solution 1: Inline Arrow Functions (Standard Modern Pattern)

The most widespread, readable, and idiomatic approach in modern React is wrapping the function call in an inline arrow function:

JSX
// ✅ Correct: The arrow function is executed ONLY when the user clicks
<button onClick={() => deleteItem(course.id)}>
Delete Course
</button>

Accessing Both Custom Arguments and the Event Object (e):

If your handler also needs access to the event object (e.g. to inspect coordinates or prevent default behavior), declare e in the arrow function parameter list:

JSX
<button onClick={(e) => handleEdit(course.id, e)}>
Edit
</button>

In the handler definition:

JSX
const handleEdit = (id, e) => {
e.stopPropagation(); // Stop event bubbling
console.log('Editing course ID:', id);
};

3. Solution 2: Higher-Order Functions (Currying)

In advanced component architectures, you can write a handler that returns another function. This is known as function currying:

JSX
export default function CourseList({ courses }) {
// Higher-order function returns an event handler pre-bound with courseId
const createDeleteHandler = (courseId) => (e) => {
console.log(`Deleting course: ${courseId}`, e.target);
};
 
return (
<ul>
{courses.map((course) => (
<li key={course.id}>
{course.title}
{/* createDeleteHandler returns the actual event handler function */}
<button onClick={createDeleteHandler(course.id)}>
Delete
</button>
</li>
))}
</ul>
);
}

4. Performance Considerations with Inline Functions

In older React documentation, developers were warned against creating inline arrow functions (() => doSomething()) due to memory allocation concerns.

In modern JavaScript engines (V8, JavaScriptCore) and modern React:

  • Creating small inline functions on render has negligible performance overhead in 99% of applications.
  • You should only optimize inline arrow functions (using useCallback) if passing handlers down to heavily memoized child components (React.memo) that render massive lists.
  • For standard components, prioritize clarity, readability, and maintainability.

Interactive Quiz

Practice Quiz

Question 1
What happens if you write <button onClick={handleRemove(item.id)}>Remove</button>?
Question 2
What is the most common and idiomatic way to pass custom arguments to an event handler in React?
Question 3
How can you pass both a custom item ID and the React SyntheticEvent e to a handler?
Question 4
What is a higher-order event handler?
Question 5
Is creating an inline arrow function inside an onClick prop acceptable in modern React?
Next Lesson

Handling Click, Change, and Submit Events

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext