1

I have a table(array of objects) in React. I have a input box/ button for each row. Currently, I m using index in react local state (for input box/button). But 'index' results in messed up table, when filtered. Read link https://www.menubar.io/react-keys-index/ and trying to use 'keys'. Can someone help for accessing the array of input boxes and buttons using keys? My code is below:

 companies.map((company,index)=>{
 return (
 <tr key={company.id}>
   <td onClick={this.props.onClick.bind(this, company)}></td>       
   <td>{company.vacancy}</td>     
   <td key={company.id}>            
         <p><input type="text" value={this.state.company.messages[index] || ''} name={this.state.company.messages[index]} onChange={this.handleMessageChange.bind(this,company,index)}/></p>
         <p><button type="button" onClick={() => this.sendSMS(company,index)}>SMS</button></p>
  </td>                          
 </tr>
   );
  })

I have companyId as unique value.

user8125765
  • 209
  • 1
  • 2
  • 16

2 Answers2

2

Since companyId is unique,it can be used as key.

In your example key should be used in tr and not in the inner td

<tr key={company.id}> - correct usage
<td key={company.id}> - Incorrect usage

Keys only make sense in the context of the surrounding array.

You can refer the Extracting Components with Keys in https://reactjs.org/docs/lists-and-keys.html which Incorrect and correct Key Usage

You can refer Understanding unique keys for array children in React.js for any operations in the array (filter in your case).

crazyCoder
  • 329
  • 1
  • 2
  • 16
1

You shouldn't use arrays to store the values of items that can rearrange because then you would also have to rearrange the array in order to maintain the correct item-to-value relation.

Use an object instead:

<input 
  type="text"
  value={this.state.company.messages[company.id] || ''}
  name={this.state.company.messages[company.id]}
  onChange={this.handleMessageChange.bind(this, company)}
/>

Your state in the constructor would then look something like:

this.state = {
  company: {
    messages: {}
  }
};

This way, your messages per company are stored as:

company: {
 messages: {
   someCompanyId: "blah blah",
   anotherCompanyId: "blah",
   ...
 }
}

This makes the storing of the values independent of index and order.

Chris
  • 57,622
  • 19
  • 111
  • 137