[reactjs] React passing parameter via onclick event using ES6 syntax

How to pass extra parameters to an onClick event using the ES6 syntax?

For instance:

handleRemove = (e) => {

}

render() {
     <button onClick={this.handleRemove}></button>
}

I want to pass an id to the handleRemove function like this:

<button onClick={this.handleRemove(id)}></button>

This question is related to reactjs

The answer is


onClick={this.handleRemove.bind(this, id)}

Use Arrow function like this:

<button onClick={()=>{this.handleRemove(id)}}></button>

Remember that in onClick={ ... }, the ... is a JavaScript expression. So

... onClick={this.handleRemove(id)}

is the same as

var val = this.handleRemove(id);
... onClick={val}

In other words, you call this.handleRemove(id) immediately, and pass that value to onClick, which isn't what you want.

Instead, you want to create a new function with one of the arguments already prefilled; essentially, you want the following:

var newFn = function() {
  var args = Array.prototype.slice.call(arguments);

  // args[0] contains the event object
  this.handleRemove.apply(this, [id].concat(args));
}
... onClick={newFn}

There is a way to express this in ES5 JavaScript: Function.prototype.bind.

... onClick={this.handleRemove.bind(this, id)}

If you use React.createClass, React automatically binds this for you on instance methods, and it may complain unless you change it to this.handleRemove.bind(null, id).

You can also simply define the function inline; this is made shorter with arrow functions if your environment or transpiler supports them:

... onClick={() => this.handleRemove(id)}

If you need access to the event, you can just pass it along:

... onClick={(evt) => this.handleRemove(id, evt)}

I use the following code:

<Button onClick={this.onSubmit} id={item.key} value={shop.ethereum}>
    Approve
</Button>

Then inside the method:

onSubmit = async event => {
    event.preventDefault();
    event.persist();
    console.log("Param passed => Eth addrs: ", event.target.value)
    console.log("Param passed => id: ", event.target.id)
    ...
}

As a result:

Param passed in event => Eth addrs: 0x4D86c35fdC080Ce449E89C6BC058E6cc4a4D49A6

Param passed in event => id: Mlz4OTBSwcgPLBzVZ7BQbwVjGip1


TL;DR:

Don't bind function (nor use arrow functions) inside render method. See official recommendations.

https://reactjs.org/docs/faq-functions.html


So, there's an accepted answer and a couple more that points the same. And also there are some comments preventing people from using bind within the render method, and also avoiding arrow functions there for the same reason (those functions will be created once again and again on each render). But there's no example, so I'm writing one.

Basically, you have to bind your functions in the constructor.

class Actions extends Component {

    static propTypes = {
        entity_id: PropTypes.number,
        contact_id: PropTypes.number,
        onReplace: PropTypes.func.isRequired,
        onTransfer: PropTypes.func.isRequired
    }

    constructor() {
        super();
        this.onReplace = this.onReplace.bind(this);
        this.onTransfer = this.onTransfer.bind(this);
    }

    onReplace() {
        this.props.onReplace(this.props.entity_id, this.props.contact_id);
    }

    onTransfer() {
        this.props.onTransfer(this.props.entity_id, this.props.contact_id);
    }

    render() {
        return (
            <div className="actions">
                <button className="btn btn-circle btn-icon-only btn-default"
                    onClick={this.onReplace}
                    title="Replace">
                        <i className="fa fa-refresh"></i>
                </button>
                <button className="btn btn-circle btn-icon-only btn-default"
                    onClick={this.onTransfer}
                    title="Transfer">
                    <i className="fa fa-share"></i>
                </button>                                 
            </div>
        )
    }
}

export default Actions

Key lines are:

constructor

this.onReplace = this.onReplace.bind(this);

method

onReplace() {
    this.props.onReplace(this.props.entity_id, this.props.contact_id);
}

render

onClick={this.onReplace}

Use the value attribute of the button element to pass the id, as

<button onClick={this.handleRemove} value={id}>Remove</button>

and then in handleRemove, read the value from event as:

handleRemove(event) {
...
 remove(event.target.value);
...
}

This way you avoid creating a new function (when compared to using an arrow function) every time this component is re-rendered.


in function component, this works great - a new React user since 2020 :)

handleRemove = (e, id) => {
    //removeById(id);
}

return(<button onClick={(e)=> handleRemove(e, id)}></button> )

I am using React-Bootstrap. The onSelect trigger for dropdowns were not allowing me to pass data. Just the event. So remember you can just set any values as attributes and pick them up from the function using javascript. Picking up those attributes you set in that event target.

    let currentTarget = event.target;
    let currentId = currentTarget.getAttribute('data-id');
    let currentValue = currentTarget.getAttribute('data-value');

Something nobody has mentioned so far is to make handleRemove return a function.

You can do something like:

handleRemove = id => event => {
  // Do stuff with id and event
}

// render...
  return <button onClick={this.handleRemove(id)} />

However all of these solutions have the downside of creating a new function on each render. Better to create a new component for Button which gets passed the id and the handleRemove separately.