Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameter in ReactJS onclick

I have this React component that has items generated from a list (with a map function). Each of those elements has a button. I want this button's onclick button to pass in a parameter to identify which list item's button was clicked.

It looks something like this.

var Component = React.createClass({
    assignItem: function(item){
        this.setState({item:item})
    },
    render: function(){
        var listItems = list.map(function(item){
        return <div>{item}
        <button onClick={this.assignItem(item)>Click</button>
        </div>
        })
        return <div>{listItems}</div>
    }
})

Of course that doesn't work. The error message says that this.assignItem is not a function. I know the official React documentation suggests this:

var handleClick = function(i, props) {
  console.log('You clicked: ' + props.items[i]);
}

function GroceryList(props) {  
  return (
    <div>
  {props.items.map(function(item, i) {
    return (
      <div onClick={handleClick.bind(this, i, props)} key={i}>{item}</div>
    );
  })}
</div>
  );
}
ReactDOM.render(
   <GroceryList items={['Apple', 'Banana', 'Cranberry']} />, mountNode
);

but that works with a function outside of the component. Since I want my function to manipulate the sate, I want to keep it within the React component.

How do I do this?

like image 703
Marie Pelletier Avatar asked Dec 05 '22 18:12

Marie Pelletier


1 Answers

Original accepted answer:

You can bind to a function on this just like the React example, however since you are rendering in a map callback you need to either pass in thisArg or use a fat arrow function:

var Component = React.createClass({
    assignItem: function(item){
        this.setState({item:item})
    },
    render: function(){
        // bind to this.assignItem
        var listItems = list.map(function(item){
            return <div>{item}
                <button onClick={this.assignItem.bind(this, item)}>Click</button>
            </div>
        }, this); // pass in this, or use fat arrow map callback
        return <div>{listItems}</div>
    }
})

Update 2017:

This is an old question using an old React API and an accordingly old answer. Today you should be using the class or functional React component API. For passing arguments to click handlers you can just write an inline fat arrow function and call through with whatever params you want. The above example ends up like this:

class MyComponent extends React.Component { // or React.PureComponent
    assignItem = item => { // bound arrow function handler
        this.setState({ item: item });
    }
    render() {
        var listItems = list.map(item => {
            // onClick is an arrow function that calls this.assignItem
            return <div>{item}
                <button onClick={e => this.assignItem(item)}>Click</button>
            </div>
        });
        return <div>{ listItems }</div>
    }
}

Note: The assignItem handler must be bound, which is done here using an arrow function as a class property.

like image 170
Aaron Beall Avatar answered Dec 29 '22 12:12

Aaron Beall