DEV Community

itric
itric

Posted on • Edited on

onClick={someFunction} VS onClick={()=>someFunction}

The difference between onClick={someFunction} and onClick={() => someFunction} in React (or JavaScript in general) lies in how and when they handle the execution of the someFunction when the click event occurs :

onClick={someFunction}

  • Direct Reference: This syntax directly references the function someFunction.
  • When Clicked: The function someFunction will be called when the onClick event is triggered (e.g., when the element is clicked).
  • No Extra Function Call: No additional function is created; React simply uses the function reference you provided.
  • Example: If someFunction is defined as function someFunction() { console.log('clicked'); }, then onClick={someFunction} will log 'clicked' when the element is clicked.

onClick={() => someFunction()}

  • Arrow Function: This syntax uses an arrow function to call someFunction.
  • Creates a New Function: Each time the component renders, a new function is created. The arrow function wraps the call to someFunction.
  • Immediate Invocation: Within the arrow function, someFunction is called immediately when the onClick event is triggered.
  • Use Case: Useful when you need to pass arguments to the function or need to do additional work before calling someFunction.
  • Example: If you want to pass an argument to someFunction, you can use onClick={() => someFunction('argument')}. This will call someFunction with 'argument' when the element is clicked.

When to Use Each

  • Direct Reference (onClick={someFunction}):
    • Use this when you want to avoid creating an extra function on each render, which can be more efficient.
    • Preferable for simple event handlers where no additional arguments or operations are needed.
  • Arrow Function (onClick={() => someFunction()}):
    • Use this when you need to pass arguments to the function or perform additional operations before calling the function.
    • Useful for inline operations or when dealing with closures.

Practical Examples

Direct Reference

function handleClick() {
  console.log('Button clicked');
}

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

Enter fullscreen mode Exit fullscreen mode
  • handleClick will be called directly when the button is clicked.

Arrow Function

function handleClick(message) {
  console.log(message);
}

<button onClick={() => handleClick('Button clicked')}>Click Me</button>

Enter fullscreen mode Exit fullscreen mode
  • The arrow function calls handleClick with the argument 'Button clicked' when the button is clicked.

Understanding these differences helps in optimizing performance and achieving the desired behavior in React components.

Top comments (31)

Collapse
 
efpage profile image
Eckehard • Edited

I don´t think this is actually correct.

A function is just just block of code between curly brackets, regardless if its defined with the function keyword or as an arrow function:

function f1(a){  return a*2 }  // function definition
const f2 = (a) => { return a*2 } // arrow function
const f3 = a => a*2 // short form of arrow function
Enter fullscreen mode Exit fullscreen mode

so, this is a bit misleading / wrong:

Each time the component renders, a new function is created.

what varies is the execution context, not the function itself. It may sound a bit petty, but may lead to serious errors. It is important to get these differences exactly, as Javascript has some strange behavoir in this point (See here)[dev.to/brythewiseguy/context-in-ja...].

If you are using only pure functions, this should not matter too much unless you use the "this" keyword (which in my eyes makes the function impure)

So, calling one of this functions is pretty much the same, and might not make any measurable difference in a well optimizes Javascript compiler:

function f1(a){  return a*2 }  // function definition
const f2 = f1 // function reference
const f3 = a => f1(a) // function call inside an arrow function
const function f4(a){ return f1(a)}
Enter fullscreen mode Exit fullscreen mode

It is more important to know, WHERE a function is defined and what it´s actual context is.

Collapse
 
tuzebra profile image
Huy Phan

so, this is a bit misleading / wrong:

Each time the component renders, a new function is created.

In the context of this article (React using JSX syntax), what the author said is correct. But to be more clear: Each time the component renders, a new anonymous function is created to pass to the onClick props.
Actually, using arrow function syntax here is not good because of the above reason, every time the parent renders, it passes a new prop value to the child, which leads the child to do the unnecessary rerender.

Collapse
 
efpage profile image
Eckehard

Maybe you can add some more details/references. Things are complicated here so its possible I´m wrong. I think it´s important if and when a new function object is created. See here

Collapse
 
hassanzohdy profile image
Hasan Zohdy

If the function receives a parameter like a we can use the same concept but with HOF (Higher Order Function) to be set like this:

const double = (value: number) => () => {
   // do whatever needed to be done
};
Enter fullscreen mode Exit fullscreen mode

And the usage will be something like:

<div onClick={double(2)} />
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mithuahammad profile image
Mithu Ahammad

it's Easy...

Collapse
 
milan_vadhel profile image
Milan Vadhel

Currying function

Collapse
 
happymalyo profile image
Mario Francisco Randrianandrasana • Edited

I think the article said about the component on each render is correct :

Each time the component renders, a new function is created.

function someFunction( ) { console.log('message') };
//here, it doesn't create a new function on click event, just call it
onClick={ someFunction } 
//here, it creates an anonymous function then call someFunction  
onClick={() => someFunction() } 

Enter fullscreen mode Exit fullscreen mode
Collapse
 
itric profile image
itric • Edited

i can't say, i fully understand you. i'm not an expert. i find it useful to share this info. Sorry for any misleading information, i'll be careful from next time. Thank you for correction

Collapse
 
efpage profile image
Eckehard

Your welcome!

Collapse
 
sloan profile image
Sloan the DEV Moderator

Hey, this article appears to have been generated with the assistance of ChatGPT or possibly some other AI tool.

We allow our community members to use AI assistance when writing articles as long as they abide by our guidelines. Please review the guidelines and edit your post to add a disclaimer.

Failure to follow these guidelines could result in DEV admin lowering the score of your post, making it less visible to the rest of the community. Or, if upon review we find this post to be particularly harmful, we may decide to unpublish it completely.

We hope you understand and take care to follow our guidelines going forward!

Collapse
 
jgdevelops profile image
Julian Gaston

Nice article. Good stuff!!

Collapse
 
efpage profile image
Eckehard

I did some research to get more clarity on this topic. See this page for more details.

Javascript functions are just objects, so they can be extended. We can add a new property to see what´s going on. Here we add a counter to a function. Each time, the function is called, the counter is increased:

// function sayHi(){
const sayHi = () =>  {
  console.log("Hi");
  sayHi.counter++;
}
sayHi.counter = 0; // initial value

sayHi(); // Hi
sayHi(); // Hi

console.log( `Called ${sayHi.counter} times` ); // Called 2 times
Enter fullscreen mode Exit fullscreen mode

So, we can clearly see, the function only exists once and is called twice. This works with regular functions and with arrow functions in the same way.

Things are a bit different if we create the complete function body inside the an arrow function like this:

run2 = () => {
  let f = function (){
    console.log("Hi2")
    f.counter ++
  }
  f.counter = 0
  return f
}

let x 
x = run2(); x()
x = run2(); x()
console.log( `Called ${x.counter} times` ); // Called 1 times
Enter fullscreen mode Exit fullscreen mode

Here, each time run2 is called, we create a new function. But this happens only, if we create the whole function body inside the arrow function. It should not happen if we create the function outside and just use a reference.

Collapse
 
syedmuhammadaliraza profile image
Syed Muhammad Ali Raza

👍

Collapse
 
raghuwarjangir profile image
Raghuwar Jangir • Edited

great content 👍for beginners it's good practice.

Collapse
 
douglaspujol profile image
Douglas Pujol

Excellent article

Collapse
 
mekkj98 profile image
keshav jha

There is alternate way in which you can use something like data-{xyz} attribute in element and onclick or on any event, you can get that attribute value using e.target.getAttribute("data-{xyz}").

function handleClick(e) {
const message = e.target.getAttribute("data-message")
console.log(message);
}

<button data-message="Button clicked" onClick={handleClick}>Click Me</button>

Collapse
 
dillonheadley profile image
Dillon Headley

If you are using data attributes you should use e.target.dataset to read them. Like e.target.dataset.message

Collapse
 
mekkj98 profile image
keshav jha • Edited

Yup, performance difference is negligible but .getAttribute is faster than dataset field some extent. That is not an excuse, the thing is i got used to .getAttribute and primarily i want to fetch only couple of data attributes in most of the scenario so i'm using .getAttribute mostly.

Collapse
 
chavansoham profile image
Chavan-Soham

So output will be "Button clicked" because you have passed this value to data-message attribute right ?

Collapse
 
gihanrangana profile image
GihanRangana

This will be the cleanest way to pass arguments to the function

function handleClick(message) {
  console.log(message);
}

<button onClick={handleClick.bind(null,"Button Clicked")}>Click Me</button>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
shepardm7 profile image
Sateek Roy • Edited

How? The .bind creates a new function every time the component is re-rendered. If we want to pass an argument to this function then the only way to prevent a new function from being created on a render is to create a memoized reference to that function using the useCallback hook.

const testFn = () => { console.log('Hello'); }
console.log(testFn.bind(null) === testFn.bind(null)); // false
Enter fullscreen mode Exit fullscreen mode

Try this code in the browser console and you'll get false as the output which proves that bind will also cause a re-render.

Collapse
 
ed1nh0 profile image
Edson Jr.

Have you actually read what you wrote?
Cleaning up your sentences a bit I got:

onClick={someFunction}
The function someFunction will be called when the onClick event is triggered

onClick={() => someFunction()}
someFunction is called immediately when the onClick event is triggered.

I didn't got it to be honest.