Saya membuat aplikasi dengan ReactNative baik untuk iOS dan android dengan file ListView
. Saat mengisi listview dengan sumber data yang valid, peringatan berikut dicetak di bagian bawah layar:
Peringatan: Setiap anak dalam larik atau iterator harus memiliki properti "kunci" yang unik. Periksa metode render
ListView
.
Apa tujuan peringatan ini? Setelah pesan yang mereka tautkan halaman ini , di mana hal-hal yang berbeda dibahas yang tidak ada hubungannya dengan react native, tetapi dengan reactjs berbasis web.
ListView saya dibuat dengan pernyataan tersebut:
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}
/>
);
}
Sumber Data saya terdiri dari sesuatu seperti:
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)
});
Dan ListView-Rows dirender dengan hal-hal seperti:
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>
);
Semuanya bekerja dengan baik dan seperti yang diharapkan, kecuali peringatan yang tampaknya sama sekali tidak masuk akal bagi saya.
Menambahkan properti kunci ke kelas "DetailItem" saya tidak menyelesaikan masalah.
Ini, apa yang sebenarnya akan diteruskan ke ListView sebagai hasil dari "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: '' } ] },
Seperti yang dilihat oleh salah satu kunci, setiap record memiliki properti kunci. Peringatan itu masih ada.
sumber
DetailItem
perlu memiliki kunci. Jika mereka sudah memiliki kunci unik, Anda perlu menunjukkan metode render lainnya (renderHeader, renderDetailItem, renderSeparator
). Mereka berfungsi dengan baik dan diharapkan sampai sumber data diubah di suatu tempat (baris dihapus, misalnya) di mana React tidak akan tahu apa yang harus dilakukan dengan mereka ketika mereka tidak memiliki pengenal unik.Jawaban:
Saya sudah punya persis masalah yang sama dengan Anda untuk sementara waktu sekarang, dan setelah melihat beberapa saran di atas, saya akhirnya menyelesaikan masalah tersebut.
Ternyata (setidaknya untuk saya), saya perlu memberikan kunci (prop yang disebut 'key') ke komponen yang saya kembalikan dari metode renderSeparator saya. Menambahkan kunci ke renderRow atau renderSectionHeader saya tidak melakukan apa-apa, tetapi menambahkannya ke renderSeparator membuat peringatan itu hilang.
Semoga membantu.
sumber
SectionList
, harus secara eksplisit menambahkan properti dengan kunci nama untuk masing-masingitem
untuk membuat RN senang.Anda perlu memberikan kunci .
Coba lakukan ini di Baris ListView Anda jika Anda memiliki properti utama:
<TouchableHighlight key={item.key} underlayColor='#dddddd'>
Jika tidak, coba tambahkan item sebagai kunci:
<TouchableHighlight key={item} underlayColor='#dddddd'>
sumber
Anda juga dapat menggunakan hitungan iterasi (i) sebagai
key
:render() { return ( <ol> {this.props.results.map((result, i) => ( <li key={i}>{result.text}</li> ))} </ol> ); }
sumber
Ubah kode Anda dari:
render() { return ( <ol> {this.props.results.map((result) => ( <li>{result.text}</li> ))} </ol> ); }
Untuk:
render() { return ( <ol> {this.props.results.map((result) => ( <li key={result.id}>{result.text}</li> ))} </ol> ); }
Kemudian diselesaikan.
sumber
Tambahkan 'kunci' prop ke komponen akar rendering dari daftar.
<ScrollView> <List> {this.state.nationalities.map((prop, key) => { return ( <ListItem key={key}> <Text>{prop.name}</Text> </ListItem> ); })} </List> </ScrollView>
sumber
Peringatan ini muncul ketika Anda tidak menambahkan kunci ke item daftar Anda. Sesuai 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> );
sumber
Saya memperbaikinya dengan menambahkan properti ke renderSeparator Component, kodenya ada di sini:
_renderSeparator(sectionID,rowID){ return ( <View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View> ); }
Kata kunci peringatan ini adalah "unik", sectionID + rowID mengembalikan nilai unik di ListView.
sumber
Periksa: key = undef !!!
Anda juga mendapat pesan peringatan:
Each child in a list should have a unique "key" prop.
jika kode Anda lengkap benar, tetapi jika aktif
someValue tidak ditentukan !!! Silakan periksa ini dulu. Anda dapat menghemat waktu berjam-jam.
sumber
Dengan asumsi metode renderDetailItem memiliki tanda tangan berikut ...
Coba lakukan ini ...
<TouchableHighlight key={rowID} underlayColor='#dddddd'>
sumber
Kode spesifik yang saya gunakan untuk memperbaiki ini adalah:
renderSeparator(sectionID, rowID, adjacentRowHighlighted) { return ( <View style={styles.separator} key={`${sectionID}-${rowID}`}/> ) }
Saya menyertakan kode khusus karena Anda memerlukan kunci yang unik - bahkan untuk pemisah. Jika Anda melakukan sesuatu yang serupa misalnya, jika Anda menyetelnya ke sebuah konstanta, Anda hanya akan mendapatkan kesalahan yang mengganggu tentang penggunaan kembali kunci. Jika Anda tidak mengetahui JSX, membuat callback ke JS untuk mengeksekusi berbagai bagian bisa sangat merepotkan.
Dan di ListView, dengan jelas melampirkan ini:
<ListView style={styles.listview} dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} renderSeparator={this.renderSeparator.bind(this)} renderSectionHeader={this.renderSectionHeader.bind(this)}/>
Penghargaan untuk coldbuffet dan Nader Dabit yang mengarahkan saya ke jalan ini.
sumber
Ini berdasarkan pemahaman saya. Semoga bermanfaat. Ini seharusnya membuat daftar komponen apa pun sebagai contoh di belakang. Tag root dari setiap komponen harus memiliki file
key
. Tidak harus unik. Tidak mungkinkey=0
,key='0'
dll. Sepertinya kuncinya tidak berguna.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>), ]; }
sumber
Sepertinya kedua syarat tersebut terpenuhi, mungkin kuncinya ('kontak') adalah masalahnya
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') ); }
sumber
Ini tidak bisa cukup ditekankan:
Kunci hanya masuk akal dalam konteks larik sekitarnya .
"Misalnya, jika Anda mengekstrak komponen ListItem, Anda harus menyimpan kunci pada elemen <ListItem /> dalam larik, bukan pada elemen <li> dalam ListItem itu sendiri." - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
sumber
Hal yang membuat saya tersandung pada masalah ini adalah saya berpikir bahwa kebutuhan akan kunci diterapkan pada apa yang tampak seperti elemen 'asli' atau DOM HTML sebagai lawan dari elemen JSX yang telah saya tentukan.
Tentu saja dengan React kita bekerja dengan DOM virtual sehingga elemen React JSX yang kita definisikan
<MyElement>
sama pentingnya dengan elemen yang terlihat seperti elemen DOM HTML asli.<div>
.Apakah itu masuk akal?
sumber
Dalam kasus saya, saya menggunakan tampilan Semantic UI React "Card". Setelah saya menambahkan kunci ke setiap kartu yang saya buat, peringatan itu hilang, misalnya:
return ( <Card fluid key={'message-results-card'}> ... </Card> )
sumber
Jika Anda menggunakan
<Fade in>
elemen untuk aplikasi react, tambahkankey={}
atribut di dalamnya juga atau Anda akan melihat kesalahan di konsol.sumber