← Back to Chapters

Passing Arguments to Event Handlers

⚛️ Passing Arguments to Event Handlers

In React, event handlers often need extra information such as IDs, names, or indexes. You can safely pass arguments using arrow functions or bind() without accidentally calling the function during render.

A common pitfall is calling the handler directly inside JSX (for example, onClick={myFunc(5)}), which makes it run immediately instead of waiting for the actual event.

? Key Concepts

  • Use arrow functions in JSX to pass custom arguments to event handlers.
  • In class components, you can use bind() or arrow functions to pass parameters.
  • React automatically passes the event object as the last argument.
  • Avoid calling the handler directly in JSX (e.g. onClick={handleClick(5)}).
  • With modern React and hooks, arrow functions are preferred over bind() in most cases.

? Passing Arguments Using Arrow Functions (Function Components)

The most common and clean way to pass arguments in React function components is to wrap the handler in an arrow function. This ensures the handler is only called when the event occurs.

? View Code Example
// Functional component: pass a name argument to the click handler
function GreetUser() {
  const greet = (name) => alert(`Hello, ${name}!`);

  return (
    <div>
      <button className="btn btn-primary me-2" onClick={() => greet("Ananya")}>
        Greet Ananya
      </button>
      <button className="btn btn-success" onClick={() => greet("Rahul")}>
        Greet Rahul
      </button>
    </div>
  );
}

Here, onClick={() => greet("Ananya")} creates a small arrow function that calls greet("Ananya") only when the user actually clicks the button.

?️ Passing Arguments in Class Components

In class components, you can use either bind() or arrow functions to pass arguments to your event handlers.

✅ Example 1: Using bind()

? View Code Example
// Class component: use bind() to pre-fill the name argument
class Welcome extends React.Component {
  handleClick(name) {
    alert(`Welcome, ${name}!`);
  }

  render() {
    return (
      <div>
        <button
          className="btn btn-warning"
          onClick={this.handleClick.bind(this, "Ananya")}
        >
          Say Hello
        </button>
      </div>
    );
  }
}

✅ Example 2: Using Arrow Function in JSX

? View Code Example
// Class component: pass argument via an arrow function
class WelcomeArrow extends React.Component {
  handleClick(name) {
    alert(`Welcome, ${name}!`);
  }

  render() {
    return (
      <button
        className="btn btn-secondary"
        onClick={() => this.handleClick("Rahul")}
      >
        Greet Rahul
      </button>
    );
  }
}

Both approaches work. Arrow functions in JSX are usually easier to read and avoid rebinding inside render(), especially when combined with hooks and functional components.

? Accessing the Event Object Along with Parameters

You can pass both a custom argument and the event object to the same handler. React automatically passes the event object as the last parameter.

? View Code Example
// Pass both a custom ID and the event object to the handler
function HandleBoth() {
  const handleClick = (id, e) => {
    alert(`Item ID: ${id}`);
    console.log("Event type:", e.type);
  };

  return (
    <button
      className="btn btn-outline-primary"
      onClick={(e) => handleClick(101, e)}
    >
      Show ID
    </button>
  );
}

Notice how the event object e is passed as the second argument and React automatically provides it when the click happens.

⚙️ Correct vs Incorrect Usage

Be careful not to call the handler directly inside JSX. That causes the function to run during render instead of on user interaction.

❌ Incorrect

? View Code Example
// Incorrect: the handler is executed immediately during render
<button onClick={handleClick(5)}>Click</button>

This version calls handleClick(5) right away while rendering, so the alert or logic will run even before the user clicks.

✅ Correct

? View Code Example
// Correct: wrap the handler call inside an arrow function
<button onClick={() => handleClick(5)}>Click</button>

Here, the arrow function is stored as the click handler, and handleClick(5) is only executed when the button is actually clicked.

? Live Output / Explanation

Imagine rendering the GreetUser component:

  • Clicking “Greet Ananya” will show an alert: Hello, Ananya!
  • Clicking “Greet Rahul” will show an alert: Hello, Rahul!
  • In the HandleBoth example, clicking the button shows an alert with Item ID: 101 and logs the event type (for example, "click") in the console.

The key idea: the alert or console log only runs when the event happens, because the handler is wrapped in an arrow function instead of being called directly during render.

? Tips & Best Practices

  • Use arrow functions in JSX to safely pass arguments to event handlers.
  • In performance-critical paths, define handlers outside of render and memoize them with useCallback().
  • Pass the event object as the last argument when combining custom parameters and the event.
  • For large lists rendered with map(), consider memoized handlers to reduce unnecessary re-renders.
  • Prefer function components with hooks; use bind() mainly for older class-based components.

? Try It Yourself

  1. Create a list of products and add a “Buy Now” button that passes the product ID to a handler.
  2. Modify the handler to log both the product ID and the event type in the console.
  3. Recreate the same feature using a class component with bind() to pass the product ID.
  4. Add console.log() statements in each handler to see when they are re-created or re-run.

Goal: Learn to pass custom arguments and event objects to React event handlers in both function and class components, without triggering unwanted renders or executing handlers too early.