简体   繁体   中英

How to pass params to an event handler within map function

I have two initial state:

element_array: [],
element_items: {
  element_type: "",
  element_name: ""
},

The form takes a input and updates state of element_items , then from there I concat element_items into element_array using:

const currentTypeElement = this.state.element_items
this.setState(function (currentState) {
  return {
    element_array: currentState.element_array.concat([currentTypeElement])
  }
});

This works fine as I can map element_array in a table. But I also want to add a 'Edit' button in the table row for each element_array object. So I added a function in my component:

handleElementEdit(prop) {
  ...
}

In my render() method I have

<table className="mb-0 table table-hover">
  <thead>
    <tr>
      <th>Element Type</th>
      <th>Element Name</th>
    </tr>
  </thead>
  <tbody>
    {this.state.element_array.map(function (prop, key) {
      return (
        <tr key={key}>
          <td>{prop.element_type}</td>
          <td>{prop.element_name}</td>
          <td>
            <button onClick={() => this.handleElementEdit(prop)}>Edit</button>
          </td>
        </tr>
      )}
    )}
  </tbody>
</table>

But when I click button It shows an error

TypeError: Cannot read property 'handleElementEdit' of undefined.

onClick event should pass prop to handleElementEdit function.

I don't understand why this is happening. Please help.

basically what happened in your case when you use the map function the scope of this is limited to that map function and this.handleElementEdit will try to find the function in map and because of it, it will throw the error.

You can use the arrow functions for it like.

{this.state.element_array.map((prop, key)=> {
    return (
        <tr key={key}>
           <td>{prop.element_type}</td>
           <td>{prop.element_name}</td>
           <td>
               <button onClick={() => this.handleElementEdit(prop)}>
               Edit
               </button>
            </td>
        </tr>
     )
   })}

Arrow function will use to retain the scope of your parent class.

Another solution is, You can bind your event handler in the constructor like:

 constructor() {
    super();
    this.handleElementEdit = this.handleElementEdit.bind(this);
  }

Also you can use the below mentioned solution, like store the this scope in variable and use that variable to bind the event.

 let that=this;
  {this.state.element_array.map(function (prop, key)=> {
        return (
            <tr key={key}>
               <td>{prop.element_type}</td>
               <td>{prop.element_name}</td>
               <td>
                   <button onClick={() => that.handleElementEdit(prop)}>
                   Edit
                   </button>
                </td>
            </tr>
         )
       })}

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