Sentry Answers>React>

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

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.

Click to Copy
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.

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

On page load, you would get the following error:

Click to Copy
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:

Click to Copy
<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.

  • Sentry BlogHow to identify fetch waterfalls in React
  • Syntax.fmReact Server Components
  • Syntax.fmWhy the jQuery Creator Uses React and Typescript
  • Syntax.fmListen to the Syntax Podcast
  • Sentry BlogReact Native Debugging and Error Tracking During App Development
  • Syntax.fmDiscussion on building native iOS and Android apps with React Native
  • SentryReact Error & Performance Monitoring
  • Sentry BlogFixing memoization-breaking re-renders in React
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,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.

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