← Back to Articles         
Event Handler in React

Event Handler in React

Published on 11 Nov 2026 22 min read React
React Fundamentals

What Is an Event Handler in React?

An event handler in React is a function that runs when a user performs an action on a UI element.

For example:

  • Clicking a button
  • Typing into an input
  • Submitting a form
  • Moving the mouse
  • Selecting an option
  • Focusing an input
  • Pressing a keyboard key
  • Checking/unchecking a checkbox
  • Copying or pasting text

React provides event handling through event props such as onClick, onChange, onSubmit, onMouseEnter, onKeyDown, and many others.

The basic idea is:

User Action
    ↓
React Event
    ↓
Event Handler Function
    ↓
Application Logic
    ↓
UI Update

For example:

const App = () => {

    const handleClick = () => {
        alert("Button clicked");
    };

    return (
        <button onClick={handleClick}>
            Click Me
        </button>
    );
};

When the user clicks the button, React calls handleClick().

The important point is that you don't call the function yourself:

onClick={handleClick}

not:

onClick={handleClick()}

The first tells React:

"When the click happens, execute this function."

The second executes the function immediately while React is rendering the component.

Event Handler Naming Convention

There is no special requirement that the function must be named handleClick, but React applications commonly use names such as:

handleClick
handleSubmit
handleChange
handleDelete
handleSave
handleLogin
handleKeyDown
handleMouseEnter

For example:

const handleSave = () => {
    console.log("Saving data...");
};

<button onClick={handleSave}>Save</button>

This naming convention makes the purpose of the function immediately understandable.

React Event Props

React uses event props with the on prefix followed by the event name.

Some commonly used events are:

React Event Purpose
onClick Mouse/button click
onDoubleClick Double click
onChange Input value changes
onSubmit Form submission
onFocus Element receives focus
onBlur Element loses focus
onMouseEnter Mouse enters an element
onMouseLeave Mouse leaves an element
onMouseMove Mouse moves over an element
onKeyDown Keyboard key is pressed
onKeyUp Keyboard key is released
onInput Input receives user input
onCopy Content is copied
onPaste Content is pasted
onCut Content is cut
onContextMenu Right-click/context menu
onScroll Element is scrolled
onDrag Element is dragged
onDrop Element is dropped

The exact event handler you use depends on what interaction your component needs.

1. Handling a Click Event

The most common event is onClick.

const App = () => {

    const handleClick = () => {
        alert("Welcome to React!");
    };

    return (
        <button onClick={handleClick}>
            Click Me
        </button>
    );
};

When the button is clicked, React invokes handleClick.

This is the standard pattern:

onClick={handleClick}

The event handler can perform any application logic:

const handleClick = () => {
    console.log("Loading data...");
    // API call
    // validation
    // state update
    // navigation
};

The handler isn't limited to displaying an alert.

2. Passing an Event Handler Directly

For very small functionality, you can define the function directly inside the JSX.

<button onClick={() => alert("Hello React")}>
    Click Me
</button>

This is useful when the logic is extremely small.

However, if the logic becomes larger, a separate function is usually easier to read:

const handleClick = () => {
    alert("Hello React");
};

<button onClick={handleClick}>
    Click Me
</button>

A good general rule is:

Small logic → inline handler can be acceptable

Complex logic → separate handler function

3. Handling an Event Object

React automatically passes an event object to your event handler.

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    console.log(event);
};

The event object contains information about the event that occurred.

For example:

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    console.log(event.currentTarget);
};

You can access things such as:

  • Which element triggered the event
  • Mouse coordinates
  • Keyboard information
  • Modifier keys
  • Target element
  • Current target
  • Event propagation information

The event object is particularly important for forms and keyboard/mouse interactions.

4. Event Handler with TypeScript

Since React with TypeScript is common, you will often explicitly type the event.

For a button click:

const handleClick = (
    event: React.MouseEvent<HTMLButtonElement>
) => {
    console.log("Button clicked");
};

For an input change:

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {
    console.log(event.target.value);
};

For a form submission:

const handleSubmit = (
    event: React.FormEvent<HTMLFormElement>
) => {
    event.preventDefault();
};

TypeScript helps ensure that you're using the correct properties for the particular event.

5. Handling Input onChange

One of the most important React events is onChange.

const App = () => {

    const handleChange = (
        event: React.ChangeEvent<HTMLInputElement>
    ) => {
        console.log(event.target.value);
    };

    return (
        <input
            type="text"
            onChange={handleChange}
        />
    );
};

As the user types:

User types: H
      ↓
onChange
      ↓
handleChange
      ↓
event.target.value = "H"

User types: e
      ↓
onChange
      ↓
handleChange
      ↓
event.target.value = "He"

This is one of the foundations of React forms.

6. Getting the Value from an Input

You can retrieve the current value using:

event.target.value

Example:

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {
    console.log(event.target.value);
};

For an input containing:

Syed

the value will be:

event.target.value

which contains:

Syed

This becomes particularly useful when combined with state.

7. Event Handler with State

A very common React pattern is:

Event
   ↓
Event Handler
   ↓
setState()
   ↓
React re-renders
   ↓
Updated UI

Example:

import { useState } from "react";

const App = () => {

    const [name, setName] = useState("");

    const handleChange = (
        event: React.ChangeEvent<HTMLInputElement>
    ) => {
        setName(event.target.value);
    };

    return (
        <div>
            <input
                value={name}
                onChange={handleChange}
            />

            <h2>Hello {name}</h2>
        </div>
    );
};

When the user types Syed, the state changes:

Input
  ↓
onChange
  ↓
handleChange
  ↓
setName("Syed")
  ↓
React re-renders
  ↓
<h2>Hello Syed</h2>

This is the foundation of controlled components in React.

8. Passing Parameters to an Event Handler

Sometimes an event handler needs additional application data.

For example:

const handleDelete = (id: number) => {
    console.log("Deleting:", id);
};

Suppose you have:

<button onClick={() => handleDelete(101)}>
    Delete
</button>

When the button is clicked:

Click
  ↓
() => handleDelete(101)
  ↓
handleDelete(101)

The important part is the arrow function:

onClick={() => handleDelete(101)}

You should not write:

onClick={handleDelete(101)}

because that executes handleDelete(101) during rendering instead of waiting for the click.

9. Passing Both Parameters and the Event

You can pass your own value as well as the React event.

const handleDelete = (
    id: number,
    event: React.MouseEvent<HTMLButtonElement>
) => {
    console.log("ID:", id);
    console.log("Event:", event);
};

Then:

<button onClick={(event) => handleDelete(101, event)}>
    Delete
</button>

This gives your function access to both:

Application data → id
Browser interaction → event

This pattern is useful for lists, tables, menus, and CRUD operations.

10. Handling Multiple Buttons

You can have different event handlers for different buttons.

const handleSave = () => {
    console.log("Saving...");
};

const handleDelete = () => {
    console.log("Deleting...");
};

const handleCancel = () => {
    console.log("Cancelling...");
};

return (
    <>
        <button onClick={handleSave}>Save</button>
        <button onClick={handleDelete}>Delete</button>
        <button onClick={handleCancel}>Cancel</button>
    </>
);

Each button has its own behavior.

This is much cleaner than creating one enormous handler containing unrelated logic.

11. Using One Handler for Multiple Elements

You can also use the same event handler for multiple elements.

const handleClick = (
    event: React.MouseEvent<HTMLButtonElement>
) => {
    console.log(event.currentTarget.textContent);
};

return (
    <>
        <button onClick={handleClick}>Save</button>
        <button onClick={handleClick}>Delete</button>
        <button onClick={handleClick}>Cancel</button>
    </>
);

The same handler receives information about which button triggered the event.

This can be useful when the behavior is common.

12. Using currentTarget vs target

This is an important concept when working with events.

Consider:

<button onClick={handleClick}>
    <span>Save</span>
</button>

If the user clicks the span, then:

event.target

may refer to:

<span>

while:

event.currentTarget

refers to:

<button>

Conceptually:

button
  └── span
       ↑
      click

target        → span
currentTarget → button

Therefore:

  • target = element where the event originated
  • currentTarget = element whose event handler is currently executing

This distinction becomes important with nested elements and event delegation.

13. Handling Form Submission

React uses onSubmit for form submission.

const handleSubmit = (
    event: React.FormEvent<HTMLFormElement>
) => {
    event.preventDefault();

    console.log("Form submitted");
};

return (
    <form onSubmit={handleSubmit}>
        <input type="text" />
        <button type="submit">Submit</button>
    </form>
);

When the user submits the form, handleSubmit executes.

The important functionality here is:

event.preventDefault();

Normally, browser form submission can cause a page navigation/reload.

React applications generally handle the submission themselves, so preventDefault() prevents the browser's default form behavior.

The flow becomes:

Submit form
    ↓
onSubmit
    ↓
handleSubmit
    ↓
preventDefault()
    ↓
Validate data
    ↓
Call API
    ↓
Display result

14. Handling Keyboard Events

React provides keyboard events such as:

onKeyDown
onKeyUp

Example:

const handleKeyDown = (
    event: React.KeyboardEvent<HTMLInputElement>
) => {
    console.log(event.key);
};

return (
    <input
        type="text"
        onKeyDown={handleKeyDown}
    />
);

If the user presses Enter:

event.key

will contain:

Enter

You can use this to perform actions based on specific keys.

For example:

const handleKeyDown = (
    event: React.KeyboardEvent<HTMLInputElement>
) => {
    if (event.key === "Enter") {
        console.log("Search");
    }
};

This is commonly used for search boxes, chat applications, forms, and keyboard shortcuts.

15. Handling onKeyUp

onKeyUp executes when the user releases a keyboard key.

const handleKeyUp = (
    event: React.KeyboardEvent<HTMLInputElement>
) => {
    console.log(event.key);
};

The distinction is:

onKeyDown → key is pressed down

onKeyUp   → key is released

For most application scenarios, onKeyDown is more commonly used when you need to react immediately to a key press.

16. Handling Focus Events

React provides:

onFocus
onBlur

Example:

const handleFocus = () => {
    console.log("Input focused");
};

const handleBlur = () => {
    console.log("Input lost focus");
};

return (
    <input
        onFocus={handleFocus}
        onBlur={handleBlur}
    />
);

This is useful for:

  • Showing validation messages
  • Highlighting active fields
  • Displaying help text
  • Validating a field after the user leaves it

A typical flow is:

User enters input
      ↓
onFocus

User enters data
      ↓
User leaves input
      ↓
onBlur
      ↓
Validate input

17. Mouse Events

React supports several mouse-related events.

For example:

<div
    onMouseEnter={handleMouseEnter}
    onMouseLeave={handleMouseLeave}
>
    Hover over me
</div>

Handlers can be used for:

onMouseEnter
onMouseLeave
onMouseMove
onMouseDown
onMouseUp
onDoubleClick

For example:

const handleDoubleClick = () => {
    console.log("Double clicked");
};

<div onDoubleClick={handleDoubleClick}>
    Double click me
</div>

These are useful for interactive UI elements.

18. Handling Checkbox Events

Checkboxes commonly use onChange.

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {
    console.log(event.target.checked);
};

return (
    <input
        type="checkbox"
        onChange={handleChange}
    />
);

For checkboxes, the important property is:

event.target.checked

It returns:

true

or:

false

For example:

const [isActive, setIsActive] = useState(false);

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {
    setIsActive(event.target.checked);
};

Now the checkbox state controls the application state.

19. Handling Select Dropdown

A <select> element also commonly uses onChange.

const handleChange = (
    event: React.ChangeEvent<HTMLSelectElement>
) => {
    console.log(event.target.value);
};

return (
    <select onChange={handleChange}>
        <option value="dotnet">.NET</option>
        <option value="react">React</option>
        <option value="azure">Azure</option>
    </select>
);

When the user selects React:

event.target.value

contains:

react

This is commonly used for filters, categories, country selection, sorting, and configuration options.

20. Handling Radio Buttons

Radio buttons also use onChange.

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {
    console.log(event.target.value);
};

return (
    <>
        <label>
            <input
                type="radio"
                name="role"
                value="developer"
                onChange={handleChange}
            />
            Developer
        </label>

        <label>
            <input
                type="radio"
                name="role"
                value="admin"
                onChange={handleChange}
            />
            Admin
        </label>
    </>
);

The selected radio button's value can then be used by your application.

21. Handling Copy, Paste and Cut

React also supports clipboard-related events.

Copy

const handleCopy = () => {
    console.log("Content copied");
};

<input onCopy={handleCopy} />

Paste

const handlePaste = () => {
    console.log("Content pasted");
};

<input onPaste={handlePaste} />

Cut

const handleCut = () => {
    console.log("Content cut");
};

<input onCut={handleCut} />

These events can be useful when implementing security restrictions, validation, analytics, or custom clipboard functionality.

22. Preventing Default Browser Behavior

React event handlers provide access to:

event.preventDefault()

For example:

const handleSubmit = (
    event: React.FormEvent<HTMLFormElement>
) => {
    event.preventDefault();

    console.log("Custom form handling");
};

preventDefault() does not stop the event itself.

It prevents the browser's default action associated with that event.

For example:

Form submission
      ↓
Browser default behavior
      ↓
Page reload/navigation

With:

event.preventDefault();

you prevent that default behavior and can handle the operation using React.

23. Stopping Event Propagation

Events can propagate through nested elements.

Consider:

<div onClick={handleParentClick}>
    <button onClick={handleButtonClick}>
        Click
    </button>
</div>

Clicking the button can cause the button's click event to propagate to the parent.

Conceptually:

Button click
    ↓
Button handler
    ↓
Parent handler

You can stop this using:

event.stopPropagation();

Example:

const handleButtonClick = (
    event: React.MouseEvent<HTMLButtonElement>
) => {
    event.stopPropagation();

    console.log("Button clicked");
};

Now the event won't continue propagating to the parent in the normal propagation path.

24. Event Bubbling

React event handling follows the browser's event propagation model.

For example:

<div onClick={() => console.log("Parent")}>
    <button onClick={() => console.log("Child")}>
        Click
    </button>
</div>

Clicking the button generally produces:

Child
Parent

The event starts at the target and bubbles upward through its ancestors.

This is called event bubbling.

It is important when designing nested interactive components.

25. Event Capturing

React also supports capture-phase event handlers.

The naming convention is:

onClickCapture

For example:

<div onClickCapture={handleParentCapture}>
    <button onClick={handleButtonClick}>
        Click
    </button>
</div>

Conceptually, event propagation has two major phases:

Capture phase
     ↓
Parent
     ↓
Child
     ↓
Target
     ↓
Bubble phase
     ↓
Child
     ↓
Parent

Capture handlers run during the capture phase.

This is less commonly required in normal application development, but it becomes useful for advanced event-handling scenarios.

26. Handling Events on Custom Components

This is a very important React concept.

Suppose you create:

const MyButton = () => {
    return <button>Save</button>;
};

You might try:

<MyButton onClick={handleClick} />

But the custom component doesn't automatically receive or forward the onClick behavior to its internal <button>.

You need to accept the prop and attach it:

type ButtonProps = {
    onClick: () => void;
};

const MyButton = ({ onClick }: ButtonProps) => {
    return (
        <button onClick={onClick}>
            Save
        </button>
    );
};

Now:

<MyButton onClick={handleClick} />

works because the custom component forwards the handler to the actual DOM button.

The important distinction is:

DOM element
    ↓
<button onClick={...} />

Custom component
    ↓
<MyButton onClick={...} />

For custom components, you decide how the event prop is passed to the underlying elements.

27. Passing Different Event Handlers to Custom Components

You can make a reusable component accept different handlers.

type ButtonProps = {
    label: string;
    onClick: () => void;
};

const CustomButton = ({
    label,
    onClick
}: ButtonProps) => {

    return (
        <button onClick={onClick}>
            {label}
        </button>
    );
};

Then:

<CustomButton
    label="Save"
    onClick={handleSave}
/>

<CustomButton
    label="Delete"
    onClick={handleDelete}
/>

The reusable component controls the UI, while the parent controls the behavior.

This is a fundamental React design pattern:

Parent Component
      ↓
passes event handler
      ↓
Child Component
      ↓
user interaction
      ↓
Child calls handler
      ↓
Parent logic executes

28. Passing the Event Handler as a Prop

An event handler is just a JavaScript function.

Therefore, it can be passed through props.

Parent:

const handleDelete = () => {
    console.log("Deleting...");
};

<DeleteButton onDelete={handleDelete} />

Child:

type DeleteButtonProps = {
    onDelete: () => void;
};

const DeleteButton = ({
    onDelete
}: DeleteButtonProps) => {

    return (
        <button onClick={onDelete}>
            Delete
        </button>
    );
};

This pattern is often called callback props.

It allows a child component to notify or trigger functionality defined by its parent.

29. Event Handler with Return Values

Event handlers generally don't need to return anything.

For example:

const handleClick = () => {
    console.log("Clicked");
};

The return value isn't normally used by React.

Therefore, event handlers are primarily used for side effects or state changes, such as:

setState(...)
API calls
navigation
validation
logging

30. Async Event Handlers

Event handlers can be asynchronous.

For example:

const handleSave = async () => {

    const response = await fetch("/api/products", {
        method: "POST"
    });

    console.log(response);
};

Then:

<button onClick={handleSave}>
    Save
</button>

When the button is clicked, React invokes the asynchronous function.

This is very common when interacting with APIs.

A typical application flow is:

Click Save
    ↓
onClick
    ↓
handleSave()
    ↓
Validate data
    ↓
await API request
    ↓
Receive response
    ↓
Update state
    ↓
UI updates

31. Handling API Calls from Events

For example:

const handleDelete = async (id: number) => {

    const response = await fetch(`/api/products/${id}`, {
        method: "DELETE"
    });

    if (response.ok) {
        console.log("Deleted successfully");
    }
};

Then:

<button onClick={() => handleDelete(10)}>
    Delete
</button>

This is a common React CRUD pattern.

The event handler becomes the entry point for the user operation.

32. Conditional Logic Inside Event Handlers

Event handlers can contain application rules.

const handleSubmit = () => {

    if (!username) {
        console.log("Username is required");
        return;
    }

    if (!password) {
        console.log("Password is required");
        return;
    }

    console.log("Login API call");
};

The handler isn't just about detecting the event.

It can coordinate the entire operation:

Event
 ↓
Validation
 ↓
Business decision
 ↓
API call
 ↓
State update
 ↓
UI feedback

For complex applications, some business logic should be moved into separate functions/services rather than putting everything into the event handler.

33. Handling Events in Lists

Suppose you have products:

const products = [
    { id: 1, name: "Laptop" },
    { id: 2, name: "Mouse" },
    { id: 3, name: "Keyboard" }
];

You can create a delete button for each product:

{products.map(product => (
    <div key={product.id}>
        <span>{product.name}</span>

        <button
            onClick={() => handleDelete(product.id)}
        >
            Delete
        </button>
    </div>
))}

Each button passes its own product ID.

For example:

Laptop    → handleDelete(1)
Mouse     → handleDelete(2)
Keyboard  → handleDelete(3)

This pattern is extremely common in CRUD applications.

34. Event Delegation

React can also take advantage of event bubbling for list interactions.

Instead of attaching handlers to every child, you can attach one handler to the parent.

For example:

const handleClick = (
    event: React.MouseEvent<HTMLDivElement>
) => {
    const target = event.target as HTMLElement;

    const id = target.dataset.id;

    if (id) {
        console.log("Clicked:", id);
    }
};

Then:

<div onClick={handleClick}>
    <button data-id="101">Product 1</button>
    <button data-id="102">Product 2</button>
    <button data-id="103">Product 3</button>
</div>

The parent handles clicks from its children.

This technique can be useful for large dynamic lists, although React's normal per-item handlers are often simpler and clearer.

35. onClick vs onChange

These events serve completely different purposes.

onClick

Used when an element is clicked:

<button onClick={handleClick}>
    Save
</button>

onChange

Used when the value of an input/control changes:

<input onChange={handleChange} />

Think of them as:

Button interaction → onClick

Input value change → onChange

36. onClick vs onDoubleClick

React provides both:

onClick
onDoubleClick

Example:

<div
    onClick={handleClick}
    onDoubleClick={handleDoubleClick}
>
    Product
</div>

A single click triggers onClick.

A double-click triggers onDoubleClick as part of the browser's mouse event sequence.

Use double-click only when it provides a meaningful interaction; single-click is generally more discoverable for users.

37. onInput vs onChange

React supports both onInput and onChange.

For normal React form development, onChange is generally the preferred choice for responding to controlled input changes:

<input
    value={name}
    onChange={handleChange}
/>

It integrates naturally with React state and controlled components.

38. Event Handler with Multiple Inputs

A single handler can manage multiple form fields.

For example:

const [form, setForm] = useState({
    username: "",
    email: "",
    password: ""
});

You can use:

const handleChange = (
    event: React.ChangeEvent<HTMLInputElement>
) => {

    const { name, value } = event.target;

    setForm(previous => ({
        ...previous,
        [name]: value
    }));
};

Then:

<input
    name="username"
    value={form.username}
    onChange={handleChange}
/>

<input
    name="email"
    value={form.email}
    onChange={handleChange}
/>

<input
    name="password"
    value={form.password}
    onChange={handleChange}
/>

The same handler can now process all three inputs.

The important mechanism is:

name → identifies the field

value → contains the new value

This is one of the most useful patterns for handling React forms.

39. Inline Event Handler

You can directly write an arrow function:

<button onClick={() => console.log("Clicked")}>
    Click
</button>

Advantages:

  • Very short
  • Convenient for simple operations
  • Useful when passing parameters

Disadvantages:

  • Can make JSX harder to read if the logic becomes large
  • Complex logic becomes difficult to maintain

40. Named Event Handler

You can define a separate function:

const handleClick = () => {
    console.log("Clicked");
};

<button onClick={handleClick}>
    Click
</button>

This is generally preferred when the logic is more than trivial.

Advantages:

  • Better readability
  • Easier testing
  • Easier reuse
  • Easier debugging
  • Keeps JSX cleaner

41. Inline Function for Passing Parameters

This is a very common pattern:

<button onClick={() => handleDelete(10)}>
    Delete
</button>

The inline function is not the actual business logic.

Its purpose is to delay execution and provide the parameter:

React click
   ↓
anonymous arrow function
   ↓
handleDelete(10)

Without the arrow function:

onClick={handleDelete(10)}

the function would execute while rendering.

42. Event Handler vs Event Listener

In traditional JavaScript, you might write:

button.addEventListener("click", handleClick);

In React, you normally write:

<button onClick={handleClick}>

The conceptual difference is:

Traditional DOM JavaScript
        ↓
addEventListener()

React
        ↓
JSX event prop
        ↓
onClick={handleClick}

React manages the event system as part of its rendering model.

You generally don't need to manually call addEventListener() for normal component interactions.

43. React Events and State Updates

One of the most important relationships to understand is:

User Event
     ↓
Event Handler
     ↓
State Update
     ↓
React Re-render
     ↓
Updated UI

For example:

const [count, setCount] = useState(0);

const handleClick = () => {
    setCount(count + 1);
};

return (
    <button onClick={handleClick}>
        Count: {count}
    </button>
);

The user doesn't directly modify the DOM.

Instead:

Click
 ↓
handleClick()
 ↓
setCount(...)
 ↓
React renders again
 ↓
New count appears

This is a fundamental principle of React.

44. Event Handler and Functional State Update

When the new state depends on the previous state, React provides the functional update form:

setCount(previous => previous + 1);

For example:

const handleClick = () => {
    setCount(previous => previous + 1);
};

This is particularly useful when multiple state updates may be queued together.

The important concept is:

previous state
      ↓
calculate new state
      ↓
set new state

rather than assuming that the current render's count variable is always the latest value.

45. Event Handler with useCallback

For advanced scenarios, you can memoize an event handler using useCallback.

const handleClick = useCallback(() => {
    console.log("Clicked");
}, []);

Then:

<button onClick={handleClick}>
    Click
</button>

useCallback is not required for normal event handling.

It becomes useful when function identity matters, particularly when passing callbacks to memoized child components or when a callback participates in dependency arrays.

Don't automatically wrap every event handler in useCallback.

46. Common Mistakes in React Event Handling

Mistake 1: Calling the handler during rendering

Wrong:

<button onClick={handleClick()}>
    Click
</button>

Correct:

<button onClick={handleClick}>
    Click
</button>

When parameters are required:

<button onClick={() => handleClick(10)}>
    Click
</button>

Mistake 2: Using HTML event attribute names

React uses:

onClick

not:

onclick

React event props use camelCase.

Mistake 3: Using string event handlers

Don't write:

<button onclick="handleClick()">

React expects a function:

<button onClick={handleClick}>

Mistake 4: Forgetting preventDefault()

For custom form submission:

const handleSubmit = (
    event: React.FormEvent<HTMLFormElement>
) => {
    event.preventDefault();

    // custom logic
};

Mistake 5: Modifying state directly

Avoid:

count = count + 1;

Instead:

setCount(previous => previous + 1);

The event handler should request a state update through the state setter.

47. Complete Event Handling Example

A realistic React component can combine several event types:

import { useState } from "react";

const UserForm = () => {

    const [name, setName] = useState("");
    const [email, setEmail] = useState("");

    const handleNameChange = (
        event: React.ChangeEvent<HTMLInputElement>
    ) => {
        setName(event.target.value);
    };

    const handleEmailChange = (
        event: React.ChangeEvent<HTMLInputElement>
    ) => {
        setEmail(event.target.value);
    };

    const handleSubmit = (
        event: React.FormEvent<HTMLFormElement>
    ) => {
        event.preventDefault();

        console.log({
            name,
            email
        });
    };

    const handleReset = () => {
        setName("");
        setEmail("");
    };

    return (
        <form onSubmit={handleSubmit}>

            <input
                type="text"
                value={name}
                onChange={handleNameChange}
                placeholder="Name"
            />

            <input
                type="email"
                value={email}
                onChange={handleEmailChange}
                placeholder="Email"
            />

            <button type="submit">
                Submit
            </button>

            <button
                type="button"
                onClick={handleReset}
            >
                Reset
            </button>

        </form>
    );
};

This component demonstrates several important React event concepts together:

User types name
      ↓
onChange
      ↓
handleNameChange
      ↓
setName()
      ↓
React re-render

User types email
      ↓
onChange
      ↓
handleEmailChange
      ↓
setEmail()
      ↓
React re-render

User submits
      ↓
onSubmit
      ↓
handleSubmit
      ↓
preventDefault()
      ↓
Process form data

User clicks Reset
      ↓
onClick
      ↓
handleReset
      ↓
Reset state
      ↓
React re-render

Event Handling Mental Model

The easiest way to understand React event handling is to remember this model:

                 USER INTERACTION
                        │
                        ▼
              React Event Prop
          onClick / onChange / onSubmit
                        │
                        ▼
                 Event Handler
                handleClick()
                        │
              ┌─────────┴─────────┐
              ▼                   ▼
         Read Event           Application
         Information             Logic
              │                   │
              └─────────┬─────────┘
                        ▼
                   State Update
                   setState()
                        │
                        ▼
                  React Re-render
                        │
                        ▼
                   Updated UI

So, an event handler is not simply a function that runs when someone clicks a button. In a real React application, it is often the entry point into an application operation.

For example, a Save button may follow this complete lifecycle:

User clicks Save
      ↓
onClick
      ↓
handleSave()
      ↓
Validate form
      ↓
Read state
      ↓
Call API
      ↓
Receive response
      ↓
Update state
      ↓
React re-renders
      ↓
Show success/error message

Most Important React Event Patterns to Remember

Scenario React Pattern
Button click onClick={handleClick}
Pass parameter onClick={() => handleClick(id)}
Input change onChange={handleChange}
Form submit onSubmit={handleSubmit}
Prevent browser behavior event.preventDefault()
Stop propagation event.stopPropagation()
Keyboard press onKeyDown={handleKeyDown}
Keyboard release onKeyUp={handleKeyUp}
Focus input onFocus={handleFocus}
Leave input onBlur={handleBlur}
Checkbox onChange + event.target.checked
Dropdown onChange + event.target.value
Mouse enter onMouseEnter
Mouse leave onMouseLeave
Double click onDoubleClick
Copy onCopy
Paste onPaste
Cut onCut
Custom component callback Pass handler through props
Async operation async event handler
State update setState() inside handler

Key Rules

  1. React event names use camelCase: onClick, onChange, onSubmit.
  2. Pass a function, don't normally call it during rendering:
    onClick={handleClick}
  3. Use an arrow function when parameters are required:
    onClick={() => handleDelete(id)}
  4. React passes the event object to the handler:
    const handleClick = (event) => { };
  5. Use preventDefault() when you need to stop browser default behavior.
  6. Use stopPropagation() when you need to stop event propagation.
  7. Use onChange for most React form value changes.
  8. Event handlers commonly update state, which causes React to render the updated UI.
  9. Event handlers can be passed to child components through props.
  10. Don't use useCallback unnecessarily; ordinary functions are sufficient for most event handlers.
  11. Use TypeScript event types such as React.MouseEvent, React.ChangeEvent, and React.FormEvent when working with TypeScript.
  12. Keep complex business logic out of giant event handlers by moving reusable logic into appropriate functions/services.

The core concept to remember is:

Event = Something happened

Event Handler = What your application should do when it happens

In React, the event system connects user interaction → application logic → state changes → UI updates.

← Back to Articles