7

When handling an onChange event, this one works:

<input type="file" onChange={this.onChange}

Not this one, that executes instantaneously the function:

<input type="file" onChange={this.onChange()}

Not this other one, doesn't execute:

<input type="file" onChange={() => this.onChange}

But this one does:

<input type="file" onChange={() => this.onChange()}

But, while the first one automatically sends the event object, the second one needs to explicitly send it:

<input type="file" onChange={(e) => this.onChange(e)}
onChange(e) {
    console.log(e.target.files[0])
}

Why is that? and when should we use one or the another?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
GWorking
  • 4,011
  • 10
  • 49
  • 90
  • Try adding `console.log(this)` to see the difference between the two working approaches – Bergi Sep 19 '18 at 19:36
  • I haven't mentioned but the binding is included: this.onChange = this.onChange.bind(this) – GWorking Sep 19 '18 at 19:40
  • In that case, an additional arrow function wrapper is completely superfluous and should not be used. – Bergi Sep 19 '18 at 19:43
  • See also regarding `bind`, https://stackoverflow.com/questions/43600967/can-i-use-arrow-function-in-constructor-of-a-react-component . This applies to React to lesser extent than to generic OOP, but `bind` is preferable in general. – Estus Flask Sep 19 '18 at 20:04

2 Answers2

16

With onChange={(e) => this.onChange(e)}, you are essentially creating a new function that calls this.onChange method during each render.

With onChange={this.onChange}, you are directly accessing this.onChange method. This method is only defined once and is used multiple times. Basically, you are avoiding creating a new function with a new render thus giving the application a slight performance enhancement

Ishwor Timilsina
  • 1,344
  • 12
  • 11
9
<input type="file" onChange={this.onChange}

This works because onChange prop is a function, then you are passing a function reference to it, so it works. And <input> is responsible for passing event parameter to it.


<input type="file" onChange={this.onChange()}

This doesn't work because you are assigning to onChange prop the result value of the onChange function. (But depending of your function, it could work)


<input type="file" onChange={() => this.onChange}

This also doesn't work because you are creating a new function, and inside it, you are using the reference to a function this.onChange you are not executing it (with parentheses).


<input type="file" onChange={() => this.onChange()}

This executes the function (you are calling this.onChange()) inside your anonymous function, but you are not passing parameters to it, so how do you expect to get event info inside this.onChange function?


<input type="file" onChange={(e) => this.onChange(e)}
onChange(e) {
    console.log(e.target.files[0])
}

This resolve my previous point, now in your anonymous function you are getting event info e, and you are passing it to your onChange function. Then it works.

Pipe
  • 2,379
  • 2
  • 19
  • 33