2015-04-01 3 views
3

я использую реагировать на монтаж двух одинаковых компонентов на странице,React.js путать с «двумя детьми с тем же ключом»

var SelectBox = React.createClass({ 
    getDefaultProps: function() { 
    return { 
     value: [] 
    }; 
    }, 
    getInitialState: function() { 
    return {checked: this.props.value,count: 1}; 
    }, 
    handleClick: function() { 
    var opt = this.state.checked; 
    opt.push({id: this.state.count, name: this.state.count}); 
    this.setState({checked: opt, count: this.state.count + 1}); 
    }, 
    render: function() { 
    var that = this; 
    var options = this.state.checked.map(item => <option key={'checked-' + that.props.name + item.id} value={item.id}>{item.name}</option>); 
    return (
     <div> 
     <select multiple={true}> 
      {options} 
     </select> 
     <button type="button" onClick={this.handleClick}>add</button> 
     </div> 
    ); 
    } 
}); 
React.render(
    <SelectBox name='one'/>, 
    document.getElementById('one') 
); 
React.render(
    <SelectBox name='two'/>, 
    document.getElementById('two') 
); 

затем нажмите кнопку «один», это нормально, но когда я нажимаю кнопку «два», некоторые из «одного» появляются в «двух», почему? это заставляет меня смущать. Консоль шоу:

Warning: flattenChildren(...): Encountered two children with the same key, `.$checked-two1`. Child keys must be unique; when two children share a key, only the first child will be used. 

а просто сделать некоторые изменения

var a = [{id: 5, name: 5}]; 
React.render(
    <SelectBox name='one' value={a}/>, 
    document.getElementById('one') 
); 

это работает должным образом. что-то не так, или это ошибка?

ответ

4

О, я считаю, настоящая причина, getDefaultProps вызывается один раз и кэшируются, что любые сложные объекты, возвращаемые getDefaultProps() будут общими для всех случаев, а не скопированными, поэтому все компоненты переключателе без явного значения проп прошло разделит тот же проверил массив в состоянии. в случае, я должен написать:

getInitialState: function() { 
    var tmp = this.props.value.concat(); 
    return {checked: tmp, count: 1}; 
    }, 
2

Нет, здесь нет ошибки, вы дважды повторяете один и тот же экземпляр компонента, что означает, что «компоненты» имеют одно и то же состояние, но когда вы проходите различные реквизиты, теперь компонент получает два состояния для отслеживания.

+0

Спасибо за ваш ответ, вы имеете в виду, что все компоненты без явного значения будут одним и тем же экземпляром? В случае, я должен предоставить явное значение для каждого компонента? – alchemist

+0

Нет, только в вашем случае и как настраивается скрипка. –

+0

@limelights, так как я могу это решить? У меня такая же проблема и, скорее всего, из-за того, что вы описали. используемый прецедент - это тостер, и когда приходит новое уведомление, я не сдвигаю массив, чтобы добавить новый в начало массива (чтобы они могли загружаться снизу), предыдущие уведомления, которые визуализируются, получают разные реквизиты, потому что они теперь будут отображаться в другом месте ... но само уведомление не меняется. –

1

Эта проблема, кажется, придумать для меня, когда я поставил ключи в стиле списка реагировать компонент, и идентификаторы, передаваемые в ключи не являются уникальными, так как ошибки описание.

, например. 2 элемента списка имеют ключ 1.

Это обычно связано с ошибкой в ​​логике настройки уникальных идентификаторов.

Для моего примера я использовал хранилище redux для состояния приложений, и я задавал идентификатор элемента items.length + 1, который был неправильным.

Это вызвало у меня two children with the same key error. Чтобы исправить это, я устанавливаю каждый новый идентификатор элемента как число itemsAdded в список с течением времени.

Он похож на ключи в базе данных, где идентификатор держит приращение, так что вы не можете иметь никаких элементов в базе данных из-за удаления их всех, однако ваш идентификатор для следующего элемента может быть 1000.

Смежные вопросы