
Passing vs. Calling Functions in Event Handlers
A common React mistake is accidentally calling a function immediately instead of passing it as an event handler callback. This can cause unexpected behavior in your application.
The Problem
// ❌ Wrong - function is called immediately during render
<button onClick={handleClick()}>Click me</button>This is problematic because:
- The function executes when the component renders, not when clicked
- If the function returns a value, that value is assigned as the handler
- Can lead to infinite loops if the handler updates state
Correct Solutions
1. Pass the Function Reference (Recommended)
// ✅ Correct - passes function reference
<button onClick={handleClick}>Click me</button>2. Use an Arrow Function for Parameters
// ✅ Correct for passing parameters
<button onClick={() => handleClick(id)}>Click me</button>
// ✅ Alternative with bind
<button onClick={handleClick.bind(null, id)}>Click me</button>3. For Async Handlers
// ✅ Correct async handler
<button onClick={async () => {
  await handleAsyncClick();
  // additional logic
}}>Click me</button>Key Differences
| Approach | When It Executes | Common Use Case | 
|---|---|---|
| onClick={handleClick} | On click | Simple click handlers | 
| onClick={handleClick()} | During render | Almost always wrong | 
| onClick={() => handleClick()} | On click | When you need to pass parameters | 
| onClick={handleClick.bind(this, arg)} | On click | Alternative parameter passing | 
Common Mistakes to Avoid
- Accidental immediate execution:
   // ❌ Wrong - calls deleteItem immediately
   <button onClick={deleteItem(id)}>Delete</button>- Returning instead of passing:
   // ❌ Wrong - passes undefined if no return
   <button onClick={setCount(count + 1)}>Increment</button>- Creating new functions unnecessarily:
   // ⚠️ Okay but creates new function each render
   <button onClick={() => handleClick()}>Click</button>
   // ✅ Better if no parameters needed
   <button onClick={handleClick}>Click</button>Performance Considerations
- Avoid creating new functions in render for frequently re-rendered components:
   // ❌ Creates new function each render (bad for performance)
   function Component() {
     return <button onClick={() => handleClick()}>Click</button>;
   }
   // ✅ Better (passes stable reference)
   function Component() {
     const handleClick = useCallback(() => {
       // handler logic
     }, [dependencies]);
     return <button onClick={handleClick}>Click</button>;
   }- For class components, bind handlers in constructor:
   class MyComponent extends React.Component {
     constructor(props) {
       super(props);
       this.handleClick = this.handleClick.bind(this);
     }
     handleClick() {
       // handler logic
     }
     render() {
       return <button onClick={this.handleClick}>Click</button>;
     }
   }