kutombawewe.net

Avvertenza: ogni bambino in un array o iteratore dovrebbe avere un puntello "chiave" univoco. Controlla il metodo di rendering di `ListView`

Ho creato un'app con ReactNative per iOS e Android con ListView . Quando si popola il listview con un'origine dati valida, il seguente avviso viene stampato nella parte inferiore dello schermo:

Avvertenza: ogni bambino in un array o iteratore dovrebbe avere un puntello "chiave" univoco. Controlla il metodo di rendering di ListView.

Qual è lo scopo di questo avvertimento? Dopo il messaggio che linkano a questa pagina , dove vengono discusse cose diverse e complete che non hanno nulla a che fare con il react native, ma con reactjs basati sul web.

Il mio ListView è costruito con quelle dichiarazioni:

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}
            />

    );
}

Il mio DataSource consiste di qualcosa come:

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

E le ListView-Rows sono renderizzate con cose come:

        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>
        );

Tutto funziona bene e come previsto, tranne l'avvertimento che sembra completamente privo di senso per me.

L'aggiunta di una proprietà chiave al mio "DetailItem" -Class non ha risolto il problema.

Questo è, ciò che realmente verrà passato a ListView come risultato di "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: '' } ] },

Come una chiave vede, ogni record ha una proprietà chiave. L'avviso esiste ancora.

64
delete

Ho avuto esattamente lo stesso problema di te per un po 'ora, e dopo aver esaminato alcuni dei suggerimenti sopra, ho finalmente risolto il problema.

Si scopre (almeno per me comunque), ho avuto bisogno di fornire una chiave (un puntello chiamato 'chiave') al componente che sto restituendo dal mio metodo renderSeparator. L'aggiunta di una chiave al mio renderRow o renderSectionHeader non ha fatto nulla, ma l'aggiunta a renderSeparator ha fatto sparire l'avviso.

Spero che sia d'aiuto.

72
coldbuffet

È necessario fornire un tasto .

Prova a farlo nelle righe di ListView se disponi di una proprietà chiave:

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

In caso contrario, prova ad aggiungere l'elemento come chiave:

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

Puoi anche utilizzare il conteggio iterativo (i) come key:

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

Cambia il tuo codice da:

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

Quindi risolto.

17
micsay

Aggiungi una "chiave" del puntello al componente di rendering della radice della lista.

<ScrollView>
      <List>
          {this.state.nationalities.map((prop, key) => {
             return (
               <ListItem key={key}>
                  <Text>{prop.name}</Text>
               </ListItem>
             );
          })}
      </List>
</ScrollView>
6
SHUJAT MUNAWAR

Questo avviso viene quando non si aggiunge una chiave agli elementi dell'elenco. Come per reagire js Documenti:

Le chiavi aiutano a Reagire a identificare quali elementi sono stati modificati, aggiunti o rimossi. Le chiavi dovrebbero essere date agli elementi all'interno dell'array per dare agli elementi un'identità stabile:

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

Il modo migliore per scegliere una chiave è utilizzare una stringa che identifichi univocamente un elemento della lista tra i suoi fratelli. Molto spesso useresti gli ID dei tuoi dati come chiavi:

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

Quando non si dispone di ID stabili per gli articoli sottoposti a rendering, è possibile utilizzare l'indice oggetto come chiave come ultima risorsa

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

L'ho risolto aggiungendo una proprietà per renderSeparator Component, il codice è qui:

_renderSeparator(sectionID,rowID){
    return (
        <View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View>
    );
}

Le parole chiave di questo avviso sono "unique", sectionID + rowID restituiscono un valore univoco in ListView.

4
bocai

Supponendo che il metodo renderDetailItem abbia la seguente firma ...

(rowData, sectionID, rowID, highlightRow) 

Prova a fare questo ...

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

Il codice specifico che ho usato per risolvere questo problema era:

  renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
    return (
      <View style={styles.separator} key={`${sectionID}-${rowID}`}/>
    )
  }

Sto includendo il codice specifico perché è necessario che le chiavi siano univoche, anche per i separatori. Se fai qualcosa di simile, ad esempio, se lo imposti su una costante, riceverai un altro fastidioso errore sul riutilizzo delle chiavi. Se non conosci JSX, la costruzione del callback in JS per eseguire le varie parti può essere un problema.

E sul ListView, ovviamente allegando questo:

<ListView
  style={styles.listview}
  dataSource={this.state.dataSource}
  renderRow={this.renderRow.bind(this)}
  renderSeparator={this.renderSeparator.bind(this)}
  renderSectionHeader={this.renderSectionHeader.bind(this)}/>

Ringraziamento a coldbuffet e Nader Dabit che mi hanno indicato questo percorso.

3
Selly

Verifica: chiave = undef !!!

Hai anche il messaggio di avviso:

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

se il tuo codice è completo, ma se attivo

<MyComponent key={someValue} />

someValue non è definito !!! Si prega di controllare prima questo. Puoi risparmiare ore.

1
Gerd

Sembra che entrambe le condizioni siano soddisfatte, forse la chiave ('contatto') è il 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

Questo non può essere sottolineato abbastanza:

I tasti hanno senso solo nel contesto dell'array circostante .

"Ad esempio, se si estrae un componente ListItem, è necessario mantenere la chiave sugli elementi <ListItem /> nell'array anziché sull'elemento <li> nel ListItem stesso." - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys

0