简体   繁体   中英

How to decide on the most efficient way to call a handler function in React?

I'm still pretty new to React, but I realize that there are two common ways to define callback functions:

// Method 1
private handleInputChange = (event) => {
    this.setState({name: event.target.value});
}
// Method 2
private handleInputChange(event){
    this.setState({name:event.target.value});
}

And inside the DOM element (for this example let's use <input> ), the handler can be called via different methods like:

// Method 1
<input
    type="text"
    onChange={this.handleInputChange}
/>

// Method 2
<input
    type="text"
    onChange={(e) => this.handleInputChange(e)}
/>

// Method 3 (assume the function don't have parameters)
<input
    type="text"
    onChange={this.handleNewThing()}
/>

My question is, which is the proper method to be used? I'm genuinely so confused between all these methods. And then I see people including bind() for some reason??

You're right, there are a bunch of ways to handle handlers (ba-dum-tss). React has been around for a while now and the face of JavaScript has changed quite a bit in that time.

There's a whole page on handling events in the React documentation, but nevertheless here's a comparison of some of the ways callbacks are handled:

class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    this.boundHandleClick = this.boundHandleClick.bind(this)
  }

  arrowHandleClick = (event) => { this.props.onClick(event.target.id) }

  boundHandleClick (event) { this.props.onClick(event.target.id) }

  boundInRenderHandleClick (event) { this.props.onClick(event.target.id) }

  unboundHandleClick (event) { this.props.onClick(event.target.id) }

  render () {
    return (
      <div>
        <button id='zero' onClick={(event) => { this.props.onClick(event.target.id) }} />
        <button id='one' onClick={arrowHandleClick} />
        <button id='two' onClick={boundHandleClick} />
        <button id='three' onClick={boundInRenderHandleClick.bind(this)} />
        <button id='four' onClick={unboundHandleClick} />
      </div>
    )
  }
}

When clicked:

  • #zero will correctly call props.onClick . The problem with this is that the anonymous function created in the render method will be recreated on every render. This is not good for performance.

  • #one will correctly call props.onClick . Because the callback is defined as a class method, it will only be created when MyComponent is instantiated (and mounted). This is an acceptable way to define a callback. Apparently it's slower than once thought , but it's also the neatest in my opinion.

  • #two will correctly call props.onClick . This is essentially the same as arrowHandleClick , only it's a bound function as opposed to an arrow function. For all intents and purposes, they're the same - but by all means dig into the differences .

  • #three will correctly call props.onClick , and it has the same result as #two , but has the negative performance impact as #zero - functions should not be created nor bound in the render method.

  • #four will not work correctly and will throw an error. When it's run, this will be referring to the element (in this case, #four ) rather than the class instance. In all other handlers, this refers to the React class instance, which has a props.onClick .

Now there is a new accepted way of writing components: using plain functions and hooks. this is a thing of the past.

const MyComponent = (props) => {
  const handleClick = event => props.handleClick(event.target.id)

  const memoizedHandleClick = React.useCallback(
    event => props.handleClick(event.target.id), 
    [props.handleClick]
  )

  return (
    <div>
      <button id='zero' onClick={event => props.handleClick(event.target.id)} />
      <button id='one' onClick={handleClick} />
      <button id='two' onClick={memoizedHandleClick} />
    </div>
  )
}

All callbacks work correctly here - the only difference is that memoizedHandleClick will not be recreated on every render, unless props.handleClick changes. In my own experience, both are acceptable and people don't really seem to mind about recreating callbacks in functional components anymore - but rather being pragmatic and addressing performance issues when you encounter them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM