Creé una aplicación con ReactNative tanto para iOS como para Android con una extensiónListView
. Al llenar la vista de lista con una fuente de datos válida, se imprime la siguiente advertencia en la parte inferior de la pantalla:
Advertencia: Cada niño en una matriz o iterador debe tener una propiedad de "clave" única. Compruebe el método de renderizado de
ListView
.
¿Cuál es el propósito de esta advertencia? Después del mensaje, enlazan a esta página , donde se discuten cosas diferentes que no tienen nada que ver con react native, sino con reactjs basados en web.
Mi ListView está construido con esas declaraciones:
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}
/>
);
}
Mi fuente de datos consta de algo como:
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)
});
Y las ListView-Rows se representan con cosas como:
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>
);
Todo funciona bien y como se esperaba, excepto la advertencia que me parece una completa tontería.
Agregar una propiedad clave a mi clase "DetailItem" no resolvió el problema.
Esto es, lo que realmente se pasará a ListView como resultado de "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: '' } ] },
Como ve una clave, cada registro tiene una propiedad clave. La advertencia aún existe.
fuente
DetailItem
es que sus s necesiten tener claves. Si ya tienen claves únicas, necesita mostrar los otros métodos de renderizado (renderHeader, renderDetailItem, renderSeparator
). Funcionan bien y se esperan hasta que la fuente de datos se modifique de alguna manera (las filas se eliminan, por ejemplo), momento en el que React no sabrá qué hacer con ellos cuando no tengan un identificador único.Respuestas:
He tenido exactamente el mismo problema que tú desde hace un tiempo, y después de ver algunas de las sugerencias anteriores, finalmente resolví el problema.
Resulta que (al menos para mí de todos modos), necesitaba proporcionar una clave (una propiedad llamada 'clave') al componente que estoy devolviendo de mi método renderSeparator. Agregar una clave a mi renderRow o renderSectionHeader no hizo nada, pero agregarlo a renderSeparator hizo que la advertencia desapareciera.
Espero que ayude.
fuente
SectionList
, tiene que agregar explícitamente una propiedad con la clave de nombre para cada unoitem
para hacer feliz a RN.Debe proporcionar una clave .
Intente hacer esto en sus ListView Rows si tiene una propiedad clave:
<TouchableHighlight key={item.key} underlayColor='#dddddd'>
De lo contrario, intente simplemente agregar el elemento como clave:
<TouchableHighlight key={item} underlayColor='#dddddd'>
fuente
También puede utilizar el recuento de iteraciones (i) como
key
:render() { return ( <ol> {this.props.results.map((result, i) => ( <li key={i}>{result.text}</li> ))} </ol> ); }
fuente
Cambie su código de:
render() { return ( <ol> {this.props.results.map((result) => ( <li>{result.text}</li> ))} </ol> ); }
A:
render() { return ( <ol> {this.props.results.map((result) => ( <li key={result.id}>{result.text}</li> ))} </ol> ); }
Luego resuelto.
fuente
Agregue una 'clave' de apoyo al componente raíz de representación de la lista.
<ScrollView> <List> {this.state.nationalities.map((prop, key) => { return ( <ListItem key={key}> <Text>{prop.name}</Text> </ListItem> ); })} </List> </ScrollView>
fuente
Esta advertencia se produce cuando no agrega una clave a los elementos de su lista. Según 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> );
fuente
Lo arreglé agregando una propiedad para renderSeparator Component, el código está aquí:
_renderSeparator(sectionID,rowID){ return ( <View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View> ); }
Las palabras clave de esta advertencia son "únicas", sectionID + rowID devuelven un valor único en ListView.
fuente
Comprobar: clave = indef !!!
También recibiste el mensaje de advertencia:
Each child in a list should have a unique "key" prop.
si su código está completo correctamente, pero si está activado
someValue no está definido !!! Por favor, compruebe esto primero. Puede ahorrar horas.
fuente
Suponiendo que el método renderDetailItem tiene la siguiente firma ...
Intenta hacer esto ...
<TouchableHighlight key={rowID} underlayColor='#dddddd'>
fuente
El código específico que utilicé para solucionar esto fue:
renderSeparator(sectionID, rowID, adjacentRowHighlighted) { return ( <View style={styles.separator} key={`${sectionID}-${rowID}`}/> ) }
Incluyo el código específico porque necesita que las claves sean únicas, incluso para los separadores. Si hace algo similar, por ejemplo, si establece esto en una constante, obtendrá otro error molesto sobre la reutilización de claves. Si no conoce JSX, construir la devolución de llamada a JS para ejecutar las distintas partes puede ser bastante complicado.
Y en ListView, obviamente adjuntando esto:
<ListView style={styles.listview} dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} renderSeparator={this.renderSeparator.bind(this)} renderSectionHeader={this.renderSectionHeader.bind(this)}/>
Gracias a Coldbuffet y Nader Dabit, quienes me señalaron este camino.
fuente
Aquí se basa en mi entendimiento. Ojalá sea útil. Se supone que debe representar una lista de cualquier componente como el ejemplo de detrás. La etiqueta raíz de cada componente debe tener una extensión
key
. No tiene por qué ser único. No puede serkey=0
,key='0'
etc. Parece que la clave es inútil.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>), ]; }
fuente
Parece que se cumplen ambas condiciones, quizás la clave ('contacto') sea el problema
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') ); }
fuente
Esto no puede ser enfatizado suficientemente:
Las claves solo tienen sentido en el contexto de la matriz circundante .
"Por ejemplo, si extrae un componente ListItem, debe mantener la clave en los elementos <ListItem /> en la matriz en lugar de en el elemento <li> en el propio ListItem". - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
fuente
Lo que me hizo tropezar con este problema fue que pensé que la necesidad de una clave se aplicaba a lo que parece "real" o elementos DOM HTML en contraposición a los elementos JSX que he definido.
Por supuesto, con React estamos trabajando con un DOM virtual, por lo que los elementos de React JSX que definimos
<MyElement>
son tan importantes para él como los elementos que parecen elementos DOM HTML reales como<div>
.¿Tiene sentido?
fuente
En mi caso, estaba usando la vista "Tarjeta" de Semantic UI React. Una vez que agregué una clave a cada tarjeta que construí, la advertencia desapareció, por ejemplo:
return ( <Card fluid key={'message-results-card'}> ... </Card> )
fuente
Si está utilizando el
<Fade in>
elemento para una aplicación de reacción, agregue unkey={}
atributo también o verá un error en la consola.fuente