Я создал приложение с ReactNative как для iOS, так и для Android с расширениемListView
. При заполнении представления списка допустимым источником данных в нижней части экрана выводится следующее предупреждение:
Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте метод рендеринга
ListView
.
Какова цель этого предупреждения? После сообщения они ссылаются на эту страницу , где обсуждаются совершенно разные вещи, которые не имеют ничего общего с react native, а с веб-реакциями.
Мой 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}
/>
);
}
Мой источник данных состоит из чего-то вроде:
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: 'xxxxxxxxx@hotmail.com',
I/ReactNativeJS( 1293): headline: 'Email',
I/ReactNativeJS( 1293): icon: 'fontawesome|envelope' },
I/ReactNativeJS( 1293): { key: 6, type: 'moreInfo', text: '', headline: '', icon: '' } ] },
Как видно из одного ключа, каждая запись имеет ключевое свойство. Предупреждение все еще существует.
источник
DetailItem
нужны ключи. Если у них уже есть уникальные ключи, вам нужно показать другие методы рендеринга (renderHeader, renderDetailItem, renderSeparator
). Они работают нормально и ожидаются до тех пор, пока источник данных каким-либо образом не будет изменен (например, строки будут удалены), после чего React не будет знать, что с ними делать, если у них нет уникального идентификатора.Ответы:
Некоторое время у меня была точно такая же проблема, как и у вас, и, посмотрев на некоторые из приведенных выше предложений, я наконец решил проблему.
Оказывается (во всяком случае, для меня) мне нужно было предоставить ключ (свойство, называемое «ключ») компоненту, который я возвращаю из моего метода renderSeparator. Добавление ключа в мой renderRow или renderSectionHeader ничего не дало, но добавление его в renderSeparator заставило предупреждение исчезнуть.
Надеюсь, это поможет.
источник
SectionList
: нужно явно добавить свойство с ключом имени для каждого,item
чтобы сделать RN счастливым.Вам нужно предоставить ключ .
Попробуйте сделать это в своих строках ListView, если у вас есть ключевое свойство:
<TouchableHighlight key={item.key} underlayColor='#dddddd'>
Если нет, попробуйте просто добавить элемент в качестве ключа:
<TouchableHighlight key={item} underlayColor='#dddddd'>
источник
Вы также можете использовать счетчик итераций (i) как
key
:render() { return ( <ol> {this.props.results.map((result, i) => ( <li key={i}>{result.text}</li> ))} </ol> ); }
источник
Измените свой код с:
render() { return ( <ol> {this.props.results.map((result) => ( <li>{result.text}</li> ))} </ol> ); }
Кому:
render() { return ( <ol> {this.props.results.map((result) => ( <li key={result.id}>{result.text}</li> ))} </ol> ); }
Потом решил.
источник
Добавьте опору 'key' к корневому компоненту рендеринга списка.
<ScrollView> <List> {this.state.nationalities.map((prop, key) => { return ( <ListItem key={key}> <Text>{prop.name}</Text> </ListItem> ); })} </List> </ScrollView>
источник
Это предупреждение появляется, когда вы не добавляете ключ к своим элементам списка. Согласно react js Docs -
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> );
источник
Я исправил это, добавив свойство в компонент renderSeparator, код здесь:
_renderSeparator(sectionID,rowID){ return ( <View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View> ); }
Ключевые слова этого предупреждения - «уникальный», sectionID + rowID возвращают уникальное значение в ListView.
источник
Проверяем: key = undef !!!
Вы также получили предупреждающее сообщение:
Each child in a list should have a unique "key" prop.
если ваш код правильный, но если включен
someValue не определено !!! Пожалуйста, сначала проверьте это. Вы можете сэкономить часы.
источник
Предполагая, что метод renderDetailItem имеет следующую сигнатуру ...
Попробуй сделать это ...
<TouchableHighlight key={rowID} underlayColor='#dddddd'>
источник
Конкретный код, который я использовал, чтобы исправить это, был:
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 и Надера Дабита, которые указали мне на этот путь.
источник
Здесь основано на моем понимании. Надеюсь, это поможет. Он должен отображать список любых компонентов в качестве примера. Корневой тег каждого компонента должен иметь расширение
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>), ]; }
источник
Похоже, что оба условия соблюдены, возможно, проблема в ключевом («контакте»)
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') ); }
источник
Это невозможно переоценить:
Ключи имеют смысл только в контексте окружающего массива .
«Например, если вы извлекаете компонент ListItem, вы должны хранить ключ в элементах <ListItem /> в массиве, а не в элементе <li> в самом ListItem». - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
источник
Что меня сбило с толку в этой проблеме, так это то, что я подумал, что необходимость в ключе применяется к тому, что выглядит как «реальные» или DOM HTML-элементы, в отличие от JSX-элементов, которые я определил.
Конечно, с React мы работаем с виртуальной DOM, поэтому определяемые нами элементы React JSX
<MyElement>
так же важны для нее, как и элементы, которые выглядят как настоящие HTML-элементы DOM<div>
.Имеет ли это смысл?
источник
В моем случае я использовал представление «Карточка» Semantic UI React. Как только я добавил ключ к каждой построенной мной карте, предупреждение исчезло, например:
return ( <Card fluid key={'message-results-card'}> ... </Card> )
источник
Если вы используете
<Fade in>
элемент для приложения реакции, добавьтеkey={}
в него также атрибут, иначе вы увидите ошибку в консоли.источник