A trick to call handler function by the element's name

7 years ago
JavaScript
ReactJS
CodePen

This is about ReactJS. Adding a button in React, sometimes we want to add the function to handle its click event. So to do this the basic way is probaby like:

class Counter extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      name: 'Basic counter',
      count: 0
    }
    this.increaseCount = this.increaseCount.bind(this)
    this.decreaseCount = this.decreaseCount.bind(this)
  }
  increaseCount(event){
    this.setState({count:this.state.count+1})
  }
  decreaseCount(event){
    this.setState({count:this.state.count-1})
  }
  render(){
    return (
      <div>
        <div>
          {this.state.name}
        </div>
        <h1>{this.state.count}</h1>
        <div>
          <button name="increaseCount" onClick={this.increaseCount}>+1</button>
          <button name="decreaseCount" onClick={this.decreaseCount}>-1</button>
        </div>
      </div>
    )
  }
}

ReactDOM.render(
  <Counter/>,
  document.getElementById('root')
);

The code is available and can be executed live at my codepen page, https://codepen.io/mjunaidi/pen/OjeEmO.

The simple trick

I have just learned a trick that is to call the handler function based on the button's name. Here is the same thing with the applied trick:

class Counter extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      name: 'Basic counter',
      count: 0
    }
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick(event) {
    eval(this[event.target.name]).bind(this)(event)
  }
  increaseCount(event){
    this.setState({count:this.state.count+1})
  }
  decreaseCount(event){
    this.setState({count:this.state.count-1})
  }
  render(){
    return (
      <div>
        <div>
          {this.state.name}
        </div>
        <h1>{this.state.count}</h1>
        <div>
          <button name="increaseCount" onClick={this.handleClick}>+1</button>
          <button name="decreaseCount" onClick={this.handleClick}>-1</button>
        </div>
      </div>
    )
  }
}

ReactDOM.render(
  <Counter/>,
  document.getElementById('root')
);

The codepen version is here https://codepen.io/mjunaidi/pen/EvBRRj.

Notice that in the constructor we simply bind single function for the click handler. Both buttons are using the same function. But inside the handleClick function, we call the function based on the button's name by calling eval function. The benefit of using this way is we don't have to bind each function to object this, because we did that in the handleClick function while calling it through eval function. The caveat is we have to make sure the button's name is exactly the same as the function's name that need to handle the action.

Adding more buttons with different handlers

When we have this, we can add more buttons with different names but still using the same click handler. We can define the action by simply create a function with the name of the button. Here is a little additional version. https://codepen.io/mjunaidi/pen/EvBLOG.

Thanks for reading!