Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте метод рендеринга `ListView`
Я создал приложение с ReactNative для iOS и Android с ListView
. При заполнении представления списка действительным источником данных в нижней части экрана выводится следующее предупреждение:
Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте метод рендеринга ListView
.
Какова цель этого предупреждения? После сообщения они ссылаются на эту страницу, где обсуждаются совершенно разные вещи, которые не имеют ничего общего с реакцией на нативную, но с веб-реакцией.
Мой ListView построен с этими утверждениями:
render() {
var store = this.props.store;
return (
<ListView
dataSource={this.state.dataSource}
renderHeader={this.renderHeader.bind(this)}
renderRow={this.renderDetailItem.bind(this)}
renderSeparator={this.renderSeparator.bind(this)}
style={styles.listView}
/>
);
}
Мой DataSource состоит из чего-то вроде:
var detailItems = [];
detailItems.push( new DetailItem('plain', store.address) );
detailItems.push( new DetailItem('map', '') );
if(store.telefon) {
detailItems.push( new DetailItem('contact', store.telefon, 'Anrufen', 'fontawesome|phone') );
}
if(store.email) {
detailItems.push( new DetailItem('contact', store.email, 'Email', 'fontawesome|envelope') );
}
detailItems.push( new DetailItem('moreInfo', '') );
this.setState({
dataSource: this.state.dataSource.cloneWithRows(detailItems)
});
И ListView-Rows отображаются с такими вещами, как:
return (
<TouchableHighlight underlayColor='#dddddd'>
<View style={styles.infoRow}>
<Icon
name={item.icon}
size={30}
color='gray'
style={styles.contactIcon}
/>
<View style={{ flex: 1}}>
<Text style={styles.headline}>{item.headline}</Text>
<Text style={styles.details}>{item.text}</Text>
</View>
<View style={styles.separator}/>
</View>
</TouchableHighlight>
);
Все работает нормально и, как и ожидалось, кроме предупреждения, которое кажется мне полной чепухой.
Добавление ключевого свойства в мой "DetailItem" -Class не решило проблему.
Вот что действительно будет передано ListView в результате "cloneWithRows":
_dataBlob:
I/ReactNativeJS( 1293): { s1:
I/ReactNativeJS( 1293): [ { key: 2,
I/ReactNativeJS( 1293): type: 'plain',
I/ReactNativeJS( 1293): text: 'xxxxxxxxxx',
I/ReactNativeJS( 1293): headline: '',
I/ReactNativeJS( 1293): icon: '' },
I/ReactNativeJS( 1293): { key: 3, type: 'map', text: '', headline: '', icon: '' },
I/ReactNativeJS( 1293): { key: 4,
I/ReactNativeJS( 1293): type: 'contact',
I/ReactNativeJS( 1293): text: '(xxxx) yyyyyy',
I/ReactNativeJS( 1293): headline: 'Anrufen',
I/ReactNativeJS( 1293): icon: 'fontawesome|phone' },
I/ReactNativeJS( 1293): { key: 5,
I/ReactNativeJS( 1293): type: 'contact',
I/ReactNativeJS( 1293): text: '[email protected]',
I/ReactNativeJS( 1293): headline: 'Email',
I/ReactNativeJS( 1293): icon: 'fontawesome|envelope' },
I/ReactNativeJS( 1293): { key: 6, type: 'moreInfo', text: '', headline: '', icon: '' } ] },
Как видно из одного ключа, каждая запись имеет ключевое свойство. Предупреждение все еще существует.
Ответы
Ответ 1
У меня уже была точно та же проблема, что и вы, и, рассмотрев некоторые из приведенных выше предложений, я, наконец, решил проблему.
Получается (по крайней мере, для меня в любом случае), мне нужно было предоставить ключ (prop под названием "ключ" ) к компоненту, который я возвращаю из метода renderSeparator. Добавление ключа к моему renderRow или renderSectionHeader ничего не делало, но добавив его в renderSeparator, предупреждение вышло.
Надеюсь, что это поможет.
Ответ 2
Вам нужно предоставить ключ.
Попробуйте сделать это в своих рядах ListView, если у вас есть свойство ключа:
<TouchableHighlight key={item.key} underlayColor='#dddddd'>
Если нет, попробуйте просто добавить элемент в качестве ключа:
<TouchableHighlight key={item} underlayColor='#dddddd'>
Ответ 3
Вы также можете использовать счетчик итераций (i) как key
:
render() {
return (
<ol>
{this.props.results.map((result, i) => (
<li key={i}>{result.text}</li>
))}
</ol>
);
}
Ответ 4
Измените свой код:
render() {
return (
<ol>
{this.props.results.map((result) => (
<li>{result.text}</li>
))}
</ol>
);
}
To:
render() {
return (
<ol>
{this.props.results.map((result) => (
<li key={result.id}>{result.text}</li>
))}
</ol>
);
}
Затем решается.
Ответ 5
Добавьте опору 'key' к корневому компоненту рендеринга списка.
<ScrollView>
<List>
{this.state.nationalities.map((prop, key) => {
return (
<ListItem key={key}>
<Text>{prop.name}</Text>
</ListItem>
);
})}
</List>
</ScrollView>
Ответ 6
Это предупреждение появляется, когда вы не добавляете ключ к своим элементам списка. Согласно реакции JS Docs -
Клавиши помогают React определить, какие элементы были изменены, добавлены или удалены. Ключи должны быть даны элементам в массиве, чтобы дать элементам устойчивую идентичность:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
Лучший способ выбрать ключ - использовать строку, которая однозначно идентифицирует элемент списка среди его братьев и сестер. Чаще всего вы используете идентификаторы из ваших данных в качестве ключей:
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
Если у вас нет стабильных идентификаторов для отображаемых элементов, вы можете использовать индекс элемента в качестве ключа в качестве крайней меры
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
Ответ 7
Я исправил это, добавив свойство для компонента renderSeparator, код здесь:
_renderSeparator(sectionID,rowID){
return (
<View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View>
);
}
Ключевым словом этого предупреждения является "уникальный", sectionID + rowID возвращают уникальное значение в ListView.
Ответ 8
Предполагая, что метод renderDetailItem имеет следующую подпись...
(rowData, sectionID, rowID, highlightRow)
Попробуйте сделать это...
<TouchableHighlight key={rowID} underlayColor='#dddddd'>
Ответ 9
Конкретный код, который я использовал, чтобы исправить это, был:
renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
return (
<View style={styles.separator} key={'${sectionID}-${rowID}'}/>
)
}
Я включил конкретный код, потому что вам нужно, чтобы ключи были уникальными - даже для разделителей. Если вы делаете что-то подобное, например, если вы устанавливаете это в качестве константы, вы просто получите еще одну досадную ошибку о повторном использовании ключей. Если вы не знаете JSX, создание обратного вызова для JS для выполнения различных частей может быть довольно сложной задачей.
И на ListView, очевидно, прикрепляя это:
<ListView
style={styles.listview}
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
renderSeparator={this.renderSeparator.bind(this)}
renderSectionHeader={this.renderSectionHeader.bind(this)}/>
Благодарю Coldbuffet и Nader Dabit, которые указали мне этот путь.
Ответ 10
Проверьте: ключ = undef !!!
Вы также получили предупреждение:
Each child in a list should have a unique "key" prop.
если ваш код завершен правильно, но если на
<MyComponent key={someValue} />
someValue не определено !!! Пожалуйста, проверьте это сначала. Вы можете сэкономить часы.
Ответ 11
Похоже, что оба условия выполнены, возможно, ключ ("контакт") является проблемой
if(store.telefon) {
detailItems.push( new DetailItem('contact', store.telefon, 'Anrufen', 'fontawesome|phone') );
}
if(store.email) {
detailItems.push( new DetailItem('contact', store.email, 'Email', 'fontawesome|envelope') );
}
Ответ 12
Это не может быть подчеркнуто достаточно:
Ключи имеют смысл только в контексте окружающего массива.
"Например, если вы извлекаете компонент ListItem, вы должны хранить ключ для элементов <ListItem/> в массиве, а не для элемента <li> в самом ListItem". - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
Ответ 13
Здесь основано на моем понимании. Надеюсь, это полезно. Предполагается, что список всех компонентов должен отображаться как пример позади. Корневой тег каждого компонента должен иметь key
. Это не должно быть уникальным. Это не может быть key=0
, key='0'
и т.д. Кажется, ключ бесполезен.
render() {
return [
(<div key={0}> div 0</div>),
(<div key={1}> div 2</div>),
(<table key={2}><tbody><tr><td> table </td></tr></tbody></table>),
(<form key={3}> form </form>),
];
}
Ответ 14
Если вы используете элемент <Fade in>
для реагирующего приложения, добавьте в него также атрибут key={}
иначе вы увидите ошибку в консоли.