Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Warning: flattenChildren(...): Encountered two children with the same key

Tags:

Could someone please explain how to fix this error

Warning: flattenChildren(...): Encountered two children with the same key

I have replicated my code below, but for some reason CodePen is not showing the error.

var FilterOptions = React.createClass({ changeOption: function(type, e) { var val = e.target.value; this.props.changeOption(val, type); },  render: function() {  return (   <div className="filter-options">     <div className="filter-option">       <select id="product" name="Product" value={this.props.product} onChange={this.changeOption.bind(this, 'product')}>       <option value=''>Product</option>       {this.props.productOptions.map(function(option) {         return (<option key={option}  value={option}>{option}</option>)       })}       </select>   </div>   </div>  );  }  }); 

Codepen

As a secondary question, I am pretty sure my reset is supposed to reset the values of the select boxes but this is also not working and just resetting the rendered results - not sure if this is related to the first problem?

Any help much appreciated

like image 374
Chris O Avatar asked Jan 17 '17 17:01

Chris O


2 Answers

It is not a good idea to use the index as the key. A key is the only thing React uses to identify DOM elements. What happens if you push an item to the list or remove something in the middle? If the key is same as before React assumes that the DOM element represents the same component as before. But that is no longer true. From: https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318

It is much better to use a unique string from each item you are mapping over as the key. Something like <option key={value.id}> or if a key does not exist, create a unique identifier by doing something like <option key={value.name + value.description}>.

like image 60
Matt Hamil Avatar answered Sep 18 '22 09:09

Matt Hamil


Adding the index as value fixed this. Thanks @azium for your sugegstion.

  <select id="product" name="Product" value={this.props.product} onChange={this.changeOption.bind(this, 'product')}>       <option value=''>Product</option>       {this.props.productOptions.map(function(option, value) {         return (<option key={value}  value={option}>{option}</option>)       })}       </select> 
like image 32
Chris O Avatar answered Sep 21 '22 09:09

Chris O