it-swarm-es.com

Advertencia: Cada niño en una matriz o iterador debe tener un prop "clave" único. Compruebe el método de renderizado de `ListView`

Construí una aplicación con ReactNative tanto para iOS como para Android con ListView . Al rellenar 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 un prop "clave" único. Compruebe el método de renderización de ListView.

¿Cuál es el propósito de esta advertencia? Después del mensaje, se vincula a la siguiente página: https://fb.me/react-warning-keys , donde se discuten cosas diferentes que no tienen nada que ver con reaccionar de forma nativa, 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 DataSource consiste en 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 de 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 me parece una completa tontería.

Agregar una propiedad clave a mi "DetailItem" -Class 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 ver una clave, cada registro tiene una propiedad clave. La advertencia todavía existe.

60
delete

He tenido exactamente el mismo problema que tú por 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 agregarla a renderSeparator hizo que la advertencia desapareciera.

Espero que ayude.

70
coldbuffet

Necesitas proporcionar una clave.

Intenta hacer esto en tus filas de ListView si tienes una propiedad clave:

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

Si no, intente simplemente agregar el elemento como clave:

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

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>
    );
}
28
Agu Dondo

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 se resuelve.

17
micsay

Agregue una prop 'clave' 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>
6
SHUJAT MUNAWAR

Esta advertencia se produce cuando no agrega una clave a los elementos de la lista. Según lo indicado por 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 dar a los elementos 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 única 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 procesados, puede usar el índice del artículo como una 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>
);
5
Jagrati

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 devuelve un valor único en ListView.

4
bocai

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

(rowData, sectionID, rowID, highlightRow) 

Intenta hacer esto ...

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

El código específico que usé para arreglar 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, solo obtendrá otro error molesto sobre la reutilización de las teclas. Si no conoce JSX, construir la devolución de llamada a JS para ejecutar las distintas partes puede ser un gran problema.

Y en el 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 que me señalaron por este camino.

3
Selly

Compruebe: clave = undef !!!

También tienes el mensaje de advertencia:

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

si su código está completo, correcto, pero si está encendido

<MyComponent key={someValue} />

algun valor es indefinido !!! Por favor, compruebe esto primero. Puedes ahorrar horas.

1
Gerd

Parece que ambas condiciones se cumplen, tal vez 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') );
}
0
Shiva Acharjee