React js onClick can't pass value to method
Easy Way
Use an arrow function:
return ( <th value={column} onClick={() => this.handleSort(column)}>{column}</th>);
This will create a new function that calls handleSort
with the right params.
Better Way
Extract it into a sub-component.The problem with using an arrow function in the render call is it will create a new function every time, which ends up causing unneeded re-renders.
If you create a sub-component, you can pass handler and use props as the arguments, which will then re-render only when the props change (because the handler reference now never changes):
Sub-component
class TableHeader extends Component { handleClick = () => { this.props.onHeaderClick(this.props.value); } render() { return ( <th onClick={this.handleClick}> {this.props.column} </th> ); }}
Main component
{this.props.defaultColumns.map((column) => ( <TableHeader value={column} onHeaderClick={this.handleSort} />))}
Old Easy Way (ES5)
Use .bind
to pass the parameter you want, this way you are binding the function with the Component context :
return ( <th value={column} onClick={this.handleSort.bind(this, column)}>{column}</th>);
There are nice answers here, and i agree with @Austin Greco (the second option with separate components)
There is another way i like, currying.
What you can do is create a function that accept a parameter (your parameter) and returns another function that accepts another parameter (the click event in this case). then you are free to do with it what ever you want.
ES5:
handleChange(param) { // param is the argument you passed to the function return function (e) { // e is the event object that returned };}
ES6:
handleChange = param => e => { // param is the argument you passed to the function // e is the event object that returned};
And you will use it this way:
<input type="text" onChange={this.handleChange(someParam)} />
Here is a full example of such usage:
Note that this approach doesn't solve the creation of a new instance on each render.
I like this approach over the other inline handlers as this one is more concise and readable in my opinion.
Edit:
As suggested in the comments below, you can cache / memoize the result of the function.
Here is a naive implementation:
Nowadays, with ES6, I feel we could use an updated answer.
return ( <th value={column} onClick={()=>this.handleSort(column)} >{column}</th>);
Basically, (for any that don't know) since onClick
is expecting a function passed to it, bind
works because it creates a copy of a function. Instead we can pass an arrow function expression that simply invokes the function we want, and preserves this
. You should never need to bind the render
method in React, but if for some reason you're losing this
in one of your component methods:
constructor(props) { super(props); this.myMethod = this.myMethod.bind(this);}