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
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.
// 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.
// 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.
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.
// Simple inline click handler for a demo button
function SimpleButton() {
return <button
onClick={() => console.log("Clicked")}
className="btn btn-light"
>
Click
</button>;
}
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.
// 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>
);
}
useCallback()For components that re-render often or pass handlers down as props, you can memoize handlers using useCallback() to keep function references stable.
// 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>
);
}
Inline functions are recreated on every render. In many apps this is fine, but in performance-sensitive areas it can cause issues such as:
Handler functions (especially when memoized with useCallback()) provide stable references that play nicely with React memoization techniques like React.memo.
| 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 |
handleClick handler.You selected: Shoes. The inline wrapper passes the correct item into handleBuy.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.
useCallback() when passing handlers to memoized child components to avoid unnecessary re-renders.useCallback() to memoize a handler and pass it to a child component wrapped with React.memo. Compare re-render behavior with and without memoization.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.