How to Handle onClick in React

What you’ll build or solve

You’ll run code when a user clicks a React element, like a button, link, or card.

When this approach works best

onClick works best when you need to:

  • Trigger an action from a button, like saving, deleting, or opening a modal.
  • Make a UI element interactive, like clicking a card to open details.
  • Choose a value from the UI, like selecting a size, filter, or tab.

Avoid using click handlers for basic navigation when a normal link is enough. Also, avoid putting slow work directly in the handler if it will freeze the UI.

Prerequisites

  • A React app set up
  • Basic JSX knowledge

Step-by-step instructions

1) Attach a click handler to an element

React’s onClick expects a function. Pass a function reference so React can call it when the click happens.

export default function Button() {
  function handleClick() {
    alert("Clicked!");
  }

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

Inline handlers for short logic

Use an inline function when the action is short.

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

Pass arguments with a wrapper function

Wrap the call so it runs on click, not during render.

export default function SizePicker() {
  function selectSize(size) {
    console.log("Selected:", size);
  }

  return (
    <button onClick={() => selectSize("M")}>
      Medium
    </button>
  );
}

What to look for:

  • The event object is available if you need it:

    onClick={(e) => { /* ... */ }}

  • preventDefault() stops default actions on links and form submits.

  • stopPropagation() stops the click from bubbling to a parent handler.

  • Don’t call the handler during render: onClick={handleClick()} runs immediately.


Examples you can copy

Example 1: Basic button action

export default function SaveButton() {
  function save() {
    console.log("Saved");
  }

  return <button onClick={save}>Save</button>;
}

Example 2: Click a card, but ignore clicks on an inner button

export default function Card() {
  function openDetails() {
    console.log("Open details");
  }

  function save(e) {
    e.stopPropagation();
    console.log("Saved");
  }

  return (
    <div
      onClick={openDetails}
      style={{ border: "1px solid #ccc", padding: 12 }}
    >
      <h3>Project</h3>
      <p>Click anywhere to open.</p>
      <button onClick={save}>Save</button>
    </div>
  );
}

stopPropagation() prevents the card’s click handler from running when the button is clicked.


Example 3: Prevent link navigation on click

export default function LinkLikeAction() {
  function handleClick(e) {
    e.preventDefault();
    console.log("Do something instead of navigating");
  }

  return (
    <a href="/pricing" onClick={handleClick}>
      Pricing
    </a>
  );
}

preventDefault() stops the browser from following the link.


Common mistakes and how to fix them

Mistake 1: Calling the handler during render

What you might do:

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

Why it breaks:

React runs handleClick() while rendering, so the click handler becomes whatever the function returned.

Fix: Pass a function reference or wrap the call.

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

<button onClick={() => handleClick("M")}>
  Medium
</button>

Mistake 2: Expecting stopPropagation() to block default navigation

What you might do:

function handleClick(e) {
  e.stopPropagation();
}

Why it breaks:

stopPropagation() stops bubbling, but it does not stop a link’s default navigation.

Fix: Use preventDefault() for default actions.

function handleClick(e) {
  e.preventDefault();
}

Troubleshooting

  • If you see the handler fire on page load, check for onClick={fn()}. Use onClick={fn} or onClick={() => fn()}.
  • If you see both a child and parent handler fire, the click is bubbling. Add e.stopPropagation() in the child handler when needed.
  • If a link still navigates, you forgot e.preventDefault() or the handler is not attached to the link you clicked.
  • If clicks do not fire, check for disabled on buttons or an overlay element blocking the click in DevTools.

Quick recap

  • Add onClick={handler} to an element.
  • Pass a function, not the result of calling a function.
  • Wrap calls to pass arguments: onClick={() => fn(arg)}.
  • Use preventDefault() to stop default actions, and stopPropagation() to stop bubbling.
  • Check for onClick={fn()} when the handler runs too early.