Uyarı: Bir dizi veya yineleyicideki her çocuk benzersiz bir "anahtar" özelliğine sahip olmalıdır. "ListView" oluşturma yöntemini kontrol edin


104

Ben sahip bir uygulama inşa ReactNative hem iOS için ve bir ile android ListView. Liste görünümü geçerli bir veri kaynağıyla doldurulurken, ekranın alt kısmında aşağıdaki uyarı yazdırılır:

Uyarı: Bir dizi veya yineleyicideki her çocuk benzersiz bir "anahtar" özelliğine sahip olmalıdır. Oluşturma yöntemini kontrol edin ListView.

Bu uyarının amacı nedir? Mesajdan sonra onlar için link bu sayfayı komple farklı şeyler yerli tepki ile ilgisi olmayan hangi tartışılır, fakat web tabanlı reactjs ile.

My ListView şu ifadelerle oluşturulmuştur:

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

    );
}

My DataSource şunun gibi bir şeyden oluşur:

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

Ve ListView Satırları aşağıdaki gibi şeylerle oluşturulur:

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

Bana tamamen saçma gibi görünen uyarı dışında her şey yolunda ve beklendiği gibi çalışıyor.

"DetailItem" -Sınıfıma bir anahtar özelliği eklemek sorunu çözmedi.

Bu, gerçekten "cloneWithRows" sonucunda ListView'a geçirilecek olan şeydir:

_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: 'xxxxxxxxx@hotmail.com',
I/ReactNativeJS( 1293):           headline: 'Email',
I/ReactNativeJS( 1293):           icon: 'fontawesome|envelope' },
I/ReactNativeJS( 1293):         { key: 6, type: 'moreInfo', text: '', headline: '', icon: '' } ] },

Bir anahtarın gördüğü gibi her kaydın bir anahtar özelliği vardır. Uyarı hala var.


1
Büyük ihtimalle DetailItemanahtarlarınızın olması gerekiyor. Zaten benzersiz anahtarlara sahiplerse, diğer oluşturma yöntemlerini ( renderHeader, renderDetailItem, renderSeparator) göstermeniz gerekir . İyi çalışıyorlar ve veri kaynağı bir şekilde değiştirilene kadar (örneğin, satırlar kaldırılana kadar) React, benzersiz bir tanımlayıcıya sahip olmadıklarında onlarla ne yapacağını bilemeyecek.
Pete TNT

Anahtarlarla ne demek istiyorsun? "Anahtar" adlı bir Mülk?
sil


Çözmez. Veri yapıma bir anahtar özellik ekledim ve orijinal soruyu daha ayrıntılı verilerle güncelledim. DataSource ile sonuçlanan düz verileri listelemek, her kayıt için bir anahtara sahiptir. Bu uyarı kalır.
sil

Diğer oluşturma yöntemlerinden de gelebilir (renderHeader, renderDetailItem, renderSeparator)
Pete TNT

Yanıtlar:


94

Bir süredir seninle tamamen aynı sorunu yaşadım ve yukarıdaki önerilerin bazılarına baktıktan sonra, sonunda sorunu çözdüm .

Görünüşe göre (en azından benim için yine de), renderSeparator yöntemimden döndürdüğüm bileşene bir anahtar ('anahtar' adlı bir destek) sağlamam gerekiyordu. RenderRow veya renderSectionHeader'a bir anahtar eklemek hiçbir şey yapmadı, ancak bunu renderSeparator'a eklemek uyarının ortadan kalkmasına neden oldu.

Umarım yardımcı olur.


Benim durumumda, renderSeparator'ı sildim ve <Separator>'umu renderRow dönüş değerinin gövdesine taşıdım.
boatcoder

Burada da aynı şey SectionList, RN'yi mutlu etmek için her biri için ad anahtarıyla açıkça bir özellik eklemek itemzorunda.
LeOn - Han Li

1
Bunu okumadan önce, JSON verilerimle ilgili bir sorun olduğunu düşündüğüm şeyi bulmak için yaklaşık 8 saat harcadım. Yığın taşması olsaydı: taco: Sana bir tane verirdim!
hoekma

76

Bir anahtar sağlamanız gerekiyor .

Bir anahtar özelliğiniz varsa bunu ListView Satırlarınızda yapmayı deneyin:

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

Değilse, öğeyi anahtar olarak eklemeyi deneyin:

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

1
Bu yanıtı daha çok beğendim, çünkü kodu var, böylece
XD'yi

34

Yineleme sayısını (i) şu şekilde de kullanabilirsiniz key:

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

2
Dizi değiştiğinde bu çalışmayabilir. Bu cevap, bir örnekle açıklıyor: stackoverflow.com/a/43892905/960857
Chris

21

Kodunuzu şuradan değiştirin:

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

Kime:

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

Sonra çözüldü.


13

Listenin oluşturma kök bileşenine bir destek 'anahtarı' ekleyin.

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

6

Bu uyarı, liste öğelerinize bir anahtar eklemediğinizde gelir. React js Docs'a göre -

Anahtarlar, React'in hangi öğelerin değiştiğini, eklendiğini veya kaldırıldığını belirlemesine yardımcı olur. Elemanlara sabit bir kimlik vermek için dizinin içindeki elemanlara anahtarlar verilmelidir:

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

Bir anahtar seçmenin en iyi yolu, kardeşleri arasında bir liste öğesini benzersiz şekilde tanımlayan bir dize kullanmaktır. Çoğu zaman verilerinizdeki kimlikleri anahtar olarak kullanırsınız:

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

Oluşturulan öğeler için kararlı kimlikleriniz olmadığında, öğe dizinini son çare olarak bir anahtar olarak kullanabilirsiniz.

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

4

RenderSeparator Bileşenine bir özellik ekleyerek bunu düzelttim, kod burada:

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

Bu uyarının anahtar kelimeleri "benzersizdir", bölüm kimliği + satır kimliği ListView'da benzersiz bir değer döndürür.


4

Kontrol edin: anahtar = undef !!!

Ayrıca uyarı mesajınız var:

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

kodunuz tamamlanmışsa, ancak açıksa

<MyComponent key={someValue} />

someValue tanımsız !!! Lütfen önce bunu kontrol edin. Saat kazanabilirsiniz.


3

RenderDetailItem yönteminin aşağıdaki imzaya sahip olduğunu varsayarsak ...

(rowData, sectionID, rowID, highlightRow) 

Bunu yapmayı dene ...

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

3

Bunu düzeltmek için kullandığım özel kod şuydu:

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

Özel kodu ekliyorum çünkü anahtarların benzersiz olması gerekiyor - ayırıcılar için bile. Benzer bir şey yaparsanız, örneğin bunu bir sabite ayarlarsanız, anahtarların yeniden kullanımıyla ilgili başka bir can sıkıcı hata alırsınız. JSX'i bilmiyorsanız, çeşitli parçaları yürütmek için JS'ye geri çağrıyı oluşturmak oldukça acı verici olabilir.

Ve ListView'da, açıkça şunu ekleyerek:

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

Beni bu yola işaret eden Coldbuffet ve Nader Dabit'e kredi.


2

İşte benim anlayışıma dayanıyor. Umarım yardımcı olur. Arkasındaki örnek olarak herhangi bir bileşenin bir listesini oluşturması gerekiyordu. Her bileşenin kök etiketinin bir key. Benzersiz olması gerekmez. Olamaz key=0, key='0'vb Bu anahtar işe yaramaz görünüyor.

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

0

Görünüşe göre her iki koşul da karşılandı, belki de anahtar ('temas') sorun

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

hayır, temas bir anahtar değildir. Arada veri yapıma "anahtar" adlı bir gayrimenkul ekledim ve sorumu daha detaylı verilerle güncelledim. Hiçbir şey yardımcı olmaz. Uyarı kalır.
sil


0

Beni bu sorunda harekete geçiren şey, tanımladığım JSX öğelerinin aksine, 'gerçek' veya DOM HTML öğelerine benzeyen bir anahtara ihtiyaç duyulduğunu düşünmemdi.

Elbette React ile sanal bir DOM ile çalışıyoruz, bu nedenle tanımladığımız React JSX öğeleri <MyElement>, gerçek DOM HTML öğelerine benzeyen öğeler kadar önemlidir <div>.

bu mantıklı mı?


0

Benim durumumda, Anlamsal UI React "Kart" görünümünü kullanıyordum. Oluşturduğum her karta bir anahtar ekledikten sonra uyarı kayboldu, örneğin:

return (
        <Card fluid key={'message-results-card'}>
          ...
        </Card>
)

-1

<Fade in>Bir react uygulaması için öğeyi kullanıyorsanız, lütfen key={}öznitelik ekleyin , aksi takdirde konsolda bir hata görürsünüz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.