Why can't the React.js onClick event pass a value to a method?

Gareth D.

The problem

When you want to pass a value as an argument to an event handler function of an onClick event, a common mistake is to try to pass the value into the function directly.

function greet(name) { alert(`hello, ${name}`); } return ( <button onClick={greet("Peter")}>Say greeting</button> );

If you do this, the function will only be called on page load. In the above code example, you’ll get an alert message pop-up with the greeting “hello, Peter” when the page is first loaded. After you click “OK” to close the alert pop-up, if you click the “Say greeting” button the pop-up won’t open again.

A similar issue would occur if the onClick event handler was a state setter function.

<button onClick={setCount(count + 1)}>Add 1</button>

On page load, you would get the following error:

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

The solution

When you call an onClick event handler function directly with an argument passed in, the function is executed when the component is mounted. This would cause the example greet function to show the alert pop-up on page load. Clicking the button afterwards does not work because the greet function has already been executed.

To fix this, use an inline function:

<button onClick={() => greet("Peter")}>Say greeting</button>

An inline function is a function that’s defined when the component is rendered. This onClick event handler is now called by React only when the button is clicked by a user.

The fix is the same if you are setting state. The reason why passing in a value to a state setter onClick event handler causes an infinite loop, if you call it without an inline function, is that the state is set when the component is rendered. This causes the component to re-render as the state is updated. The state is then set again when the component is re-rendered, which causes another re-render. This continues and causes an infinite loop.

One thing to note is that using an arrow function in the rendered component creates a new function each time the component re-renders. You don’t need to worry about performance issues from it, unless you find that it’s slowing down your app. You can read more about this in the following article: React, Inline Functions, and Performance.

Get Started With Sentry

Get actionable, code-level insights to resolve React performance bottlenecks and errors.

  1. Create a free Sentry account

  2. Create a React project and note your DSN

  3. Grab the Sentry React SDK

npm install @sentry/react
  1. Configure your DSN
import React from "react"; import ReactDOM from "react-dom"; import * as Sentry from "@sentry/react"; import App from "./App"; Sentry.init({ dsn: "https://<key>@sentry.io/<project>" }); ReactDOM.render(<App />, document.getElementById("root"));

Check our documentation for the latest instructions.

Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

Share on Twitter
Bookmark this page
Ask a questionJoin the discussion

Related Answers

A better experience for your users. An easier life for your developers.

    TwitterGitHubDribbbleLinkedinDiscord
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.