← Back to Chapters

Inline vs Handler Functions

⚛️ Inline vs Handler Functions

? Quick Overview

In React, you can attach event logic either directly in JSX as an inline function or by using a separate named handler function. Both approaches work, but they differ in readability, reusability, and performance.

As your components grow and re-render more frequently, choosing the right style becomes important for cleaner code and smoother performance.

Inline ⇒ Short & quick   Handler ⇒ Clean & reusable

? Key Concepts

  • Inline functions: Event logic is written directly inside JSX.
  • Handler functions: Logic is defined separately and referenced by name.
  • Reusability: Handlers can be reused across elements and components.
  • Performance: Inline functions are recreated on every render; handlers keep a stable reference.
  • Best practice: Use inline for very simple, one-off logic; prefer handlers for anything non-trivial.

? Syntax & Theory

Inline Event Functions

Inline functions define the event logic directly inside the JSX element. They are ideal for short, one-line actions like alerts or simple logging.

? View Code Example
// Inline handler: logic is written directly inside JSX
function InlineExample() {
  return (
    <button
      className="btn btn-primary"
      onClick={() => alert("Inline click!")}
    >
      Click Me
    </button>
  );
}

This pattern is very readable for small actions, but remember that the arrow function inside onClick is recreated every time the component renders.

Separate Handler Functions

With handler functions, you define the event logic once (usually inside the component) and then pass the function reference to JSX. This improves clarity, reuse, and performance.

? View Code Example
// Handler function: logic is separated from JSX
function HandlerExample() {
  const handleClick = () => {
    alert("Handler function clicked!");
  };

  return (
    <button className="btn btn-success" onClick={handleClick}>
      Click Me
    </button>
  );
}

Here, handleClick is defined once, so React reuses the same function reference on each render. This becomes especially useful in components with many elements or frequent updates.

? Code Examples

1️⃣ Simple Inline Handler

Use an inline handler when the logic is tiny, not reused, and performance impact is negligible—such as a quick console log or demo click.

? View Code Example
// Simple inline click handler for a demo button
function SimpleButton() {
  return <button
    onClick={() => console.log("Clicked")}
    className="btn btn-light"
  >
    Click
  </button>;
}

2️⃣ Handler with Parameters in a List

When dealing with lists, it is common to pass additional data (like the current item) to a handler. Inline functions are often used here to pass arguments, while the heavy logic stays inside the handler.

? View Code Example
// Combining a reusable handler with inline wrappers in a list
function ProductList() {
  const products = ["Shoes", "Bag", "Watch"];

  const handleBuy = (item) => {
    alert(`You selected: ${item}`);
  };

  return (
    <ul>
      {products.map((item) => (
        <li key={item}>
          {item}
          <button
            className="btn btn-outline-info btn-sm ms-2"
            onClick={() => handleBuy(item)}
          >
            Buy
          </button>
        </li>
      ))}
    </ul>
  );
}

3️⃣ Optimized Handler with useCallback()

For components that re-render often or pass handlers down as props, you can memoize handlers using useCallback() to keep function references stable.

? View Code Example
// Memoizing handler to avoid unnecessary re-creations on re-render
import React, { useCallback } from "react";

function OptimizedHandler() {
  const handleClick = useCallback(() => {
    alert("Optimized handler!");
  }, []);

  return (
    <button className="btn btn-warning" onClick={handleClick}>
      Optimized
    </button>
  );
}

? Performance Considerations

Inline functions are recreated on every render. In many apps this is fine, but in performance-sensitive areas it can cause issues such as:

  • ⚠️ Unnecessary re-renders when inline functions are passed as props to child components.
  • ⚠️ Extra overhead when rendering large lists or complex UIs repeatedly.

Handler functions (especially when memoized with useCallback()) provide stable references that play nicely with React memoization techniques like React.memo.

? Comparison Summary

Aspect Inline Function Handler Function
Readability Good for small logic Better for complex logic
Reusability Limited High (can be reused)
Performance Creates new function every render Stable reference across renders
Recommended Use Simple, one-off event handling Reusable and optimized components

? Live Output & Explanation

What happens when you click?

  • InlineExample / SimpleButton: Clicking the button immediately shows an alert or logs to the console using the inline arrow function.
  • HandlerExample: The same alert is triggered, but via the reusable handleClick handler.
  • ProductList: Clicking Buy on each item shows a message like You selected: Shoes. The inline wrapper passes the correct item into handleBuy.
  • OptimizedHandler: Each click shows an alert, but the underlying handler function stays memoized between renders.

From the user’s perspective, the UI behavior is the same. The difference is mostly about how clean, reusable, and performant your code is under the hood.

? Tips & Best Practices

  • Use inline handlers for quick, throwaway logic like simple logs or demos.
  • Prefer named handler functions in reusable or frequently updated components.
  • Group complex logic inside handlers instead of stuffing JSX with conditions and calculations.
  • Use useCallback() when passing handlers to memoized child components to avoid unnecessary re-renders.
  • Keep JSX focused on structure and layout; keep business logic in handlers.

? Try It Yourself / Practice Tasks

  1. Create two buttons — one with an inline handler, one with a separate handler. Add console logs to see which functions are recreated on each render.
  2. Build a small product list using both inline handlers and named handlers. Measure or log renders to see the impact.
  3. Use useCallback() to memoize a handler and pass it to a child component wrapped with React.memo. Compare re-render behavior with and without memoization.
  4. Refactor an existing component that overuses inline handlers by extracting them into named functions. Check if the code becomes easier to read and test.

Goal: Understand when to choose inline vs handler functions in React, how they affect performance, and how to structure your components for clean, efficient event handling.