-2

I am wondering why some function calls work without parentheses? How do you know when it is appropriate not to use parentheses after function name? See example below. Why doesn't the 3rd line not work?

onClick={this.validate} // why does function work here without parentheses?
onKeyPress={e => e.key === 'Enter' && this.validate()} // works
onKeyPress={e => e.key === 'Enter' && this.validate} // doesn't work
P Varga
  • 19,174
  • 12
  • 70
  • 108
Michael
  • 403
  • 1
  • 9
  • 28
  • 3
    In the first line, `this.validate` is a function that is not being immediately invoked or called. It's being stored for later. The code says "when clicked, I want you to call `this.validate`". In the example on line 2, that's a totally different context. There, you actually want to call it because its return value is being evaluated as part of a boolean expression rather than stored for later use. Line three says, "is the key equal to "Enter" and is this function definition truthy?" which doesn't make sense here (although you may want to ask whether a function var is defined, i.e. truthy). – ggorlen May 08 '19 at 20:07
  • @yury I'm not sure if this duplicate is appropriate. Yes it is definetly a good read for the OP, however we might benefit from an answer taking JS / React into account. That the answer below received two upvotes is a clear indicator of that. – Jonas Wilms May 08 '19 at 20:29

1 Answers1

3

onClick is an attribute that takes a function - under the hood, React, when receiving <some-element onClick={someFunction}/>, saves someFunction for later (notice that it doesn't call the function), and then calls the function when the user clicks. Note that you can rewrite this as <some-element onClick={(...args) => someFunction(...args)}/>, if that makes more sense to you.

Now here's what happens when the user presses on an element where onKeyPress={e => e.key === 'Enter' && this.validate()} is present:

  1. The function e => e.key === 'Enter' && this.validate() is called
  2. e.key === 'Enter' && this.validate() is evaluated
  3. e.key === 'Enter' is evaluated. If it evaluates to true, then:
  4. this.validate() is called and evaluated as a boolean

Notice how it is slighly different than when onKeyPress={e => e.key === 'Enter' && this.validate} is written instead:

  1. The function e => e.key === 'Enter' && this.validate is called
  2. e.key === 'Enter' && this.validate is evaluated
  3. e.key === 'Enter' is evaluated. If it evaluates to true, then:
  4. this.validate is evaluated as a boolean. If the function exists, it is coerced into the boolean true, else this.validate evaluates to undefined, which is coerced into the boolean false. Notice how this.validate did not get called. I'd regard this as a bug, except if you expressively want this behavior to happen.
P Varga
  • 19,174
  • 12
  • 70
  • 108
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
  • 1
    Nothing is coerced into a boolean though. – Jonas Wilms May 08 '19 at 20:26
  • Well, I was just trying to explain the algorithm on a high-level. Of *course* "coercion" and "cast" are not *exactly* true, IMO but they explain what's happening. – Nino Filiu May 08 '19 at 20:41
  • No, thats not happening at all. Functions are just truthy. Nothing is casted or coerced into a boolean. Actually if `e.key === "Enter"` is truthy, the last part will just be evaluated and returned. – Jonas Wilms May 08 '19 at 20:42