sectionlist react lista item flatlist facebook listview reactjs react-native

facebook - lista - scrollview react native



Advertencia: cada elemento secundario en una matriz o iterador debe tener un accesorio único "clave". Verifique el método de renderizado de `ListView` (14)

Creé una aplicación con ReactNative tanto para iOS como para Android con ListView . Al llenar la vista de lista con una fuente de datos válida, la siguiente advertencia se imprime en la parte inferior de la pantalla:

Advertencia: cada elemento secundario en una matriz o iterador debe tener un accesorio "clave" único. Verifique 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 diferentes cosas que no tienen nada que ver con react native, sino con reactjs basado 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 filas ListView 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 parece ser una completa tontería para mí.

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 se ve en una clave, cada registro tiene una propiedad clave. La advertencia aún existe.


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>


Aquí se basa en mi comprensión. Espero que sea útil. Se supone que representa una lista de cualquier componente como el ejemplo detrás. La etiqueta raíz de cada componente debe tener una key . No tiene que ser único. No puede ser key=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>), ]; }


Cambia tu 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> ); }

Entonces resuelto.


Comprobar: clave = undef !!!

También recibiste el mensaje de advertencia:

Each child in a list should have a unique "key" prop.

si su código está completo bien, pero si está activado

<MyComponent key={someValue} />

someValue es indefinido !!! Por favor verifique esto primero. Puedes ahorrar horas.


El código específico que usé 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 las 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 a Nader Dabit que me señalaron este camino.


Esta advertencia se produce cuando no agrega una clave a los elementos de su lista. Según react js Docs:

Las teclas ayudan a React a identificar qué elementos han cambiado, se agregan o se eliminan. Se deben dar claves a los elementos dentro de la matriz para darles una identidad estable:

const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> );

La mejor manera de elegir una clave es usar una cadena que identifique de forma exclusiva un elemento de la lista entre sus hermanos. La mayoría de las veces usaría ID de sus datos como claves:

const todoItems = todos.map((todo) => <li key={todo.id}> {todo.text} </li> );

Cuando no tiene ID estables para los elementos renderizados, puede usar el índice de elementos como clave como último recurso

const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> );



He tenido exactamente el mismo problema que tú por un tiempo, y después de mirar algunas de las sugerencias anteriores, finalmente resolví el problema.

Resulta que (al menos para mí de todos modos), necesitaba proporcionar una clave (un accesorio llamado ''clave'') al componente que estoy volviendo 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.


Lo arreglé agregando una propiedad a 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 "único", sectionID + rowID devuelven un valor único en ListView.


Necesita proporcionar una clave .

Intente hacer esto en sus filas ListView si tiene una propiedad clave:

<TouchableHighlight key={item.key} underlayColor=''#dddddd''>

Si no, intente simplemente agregar el elemento como clave:

<TouchableHighlight key={item} underlayColor=''#dddddd''>


Parece que ambas condiciones se cumplen, quizás la clave (''contacto'') es 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'') ); }


Si está utilizando el elemento <Fade in> para una aplicación de reacción, agregue también el atributo key={} o verá un error en la consola.


Suponiendo que el método renderDetailItem tiene la siguiente firma ...

(rowData, sectionID, rowID, highlightRow)

Intenta hacer esto ...

<TouchableHighlight key={rowID} underlayColor=''#dddddd''>


También puede usar el recuento de iteraciones (i) como key :

render() { return ( <ol> {this.props.results.map((result, i) => ( <li key={i}>{result.text}</li> ))} </ol> ); }