警告:配列またはイテレータの各子には、一意の「キー」小道具が必要です。`ListView`のrenderメソッドを確認してください


102

iOSとAndroidの両方でReactNativeを使用してアプリを作成しましたListView。リストビューに有効なデータソースを入力すると、画面の下部に次の警告が出力されます。

警告:配列またはイテレータの各子には、一意の「キー」プロップが必要です。のrenderメソッドを確認してくださいListView

この警告の目的は何ですか?メッセージの後、彼らはこのページにリンクします。そこでは、react nativeとは関係がなく、Webベースのreactjsとは関係のない完全に異なることが説明されています。

私のListViewは、次のステートメントで構築されています。

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

    );
}

私のデータソースは次のようなもので構成されています。

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

そして、ListView-Rowsは次のようなものでレンダリングされます。

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

私にはまったくナンセンスだと思われる警告を除いて、すべてが正常に機能し、期待どおりに機能します。

「DetailItem」クラスにキープロパティを追加しても問題は解決しませんでした。

これは、「cloneWithRows」の結果として実際にListViewに渡されるものです。

_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: '' } ] },

1つのキーが示すように、各レコードにはキープロパティがあります。警告はまだ存在します。


1
ほとんどDetailItemの場合、キーが必要です。それらがすでに一意のキーを持っている場合は、他のレンダリングメソッドを表示する必要があります(renderHeader, renderDetailItem, renderSeparator)。それらは正常に機能しており、データソースが何らかの方法で変更されるまで(たとえば、行が削除されるまで)期待されます。その時点で、Reactは、一意の識別子がない場合、それらをどう処理するかを知りません。
ピートTNT

「キー」とはどういう意味ですか?「キー」と呼ばれるプロパティ?
削除


それはそれを解決しません。データ構造にキープロパティを追加し、元の質問をより詳細なデータで更新しました。データソースの結果となるプレーンデータの一覧表示には、レコードごとにキーがあります。この警告は残ります。
2016年

他のレンダリングメソッド(renderHeader、renderDetailItem、renderSeparator)からも取得される可能性があります
Pete TNT

回答:


93

私はしばらくの間あなたとまったく同じ問題を抱えていました、そして上記の提案のいくつかを見た後、私はついに問題を解決しました。

結局のところ(少なくとも私にとっては)、renderSeparatorメソッドから返すコンポーネントにキー(「key」と呼ばれる小道具)を提供する必要がありました。renderRowまたはrenderSectionHeaderにキーを追加しても何も起こりませんでしたが、renderSeparatorにキーを追加すると、警告が消えました。

お役に立てば幸いです。


私の場合、renderSeparatorを削除し、<Separator>をrenderRowの戻り値の本体に移動しました。
ボートコーダー2016年

ここでも同じことが言えますが、RNを満足させるには、それぞれにSectionList名前キーを持つプロパティを明示的に追加する必要がありますitem
LeOn-Han Li 2017年

1
これを読む前に、JSONデータの問題だと思ったものを追跡するのに約8時間を無駄にしました。スタックオーバーフローがあった場合:taco:1つあげます!
hoekma 2018

76

キーを提供する必要があります

キープロパティがある場合は、ListView行でこれを実行してみてください。

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

そうでない場合は、アイテムをキーとして追加してみてください。

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

1
XDをコピーできるコードがあるので、この回答がもっと好きです
Jovylle Bermudez

34

反復回数(i)をkey:として使用することもできます。

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

2
アレイが変更された場合、これは機能しない可能性があります。この答えは例でそれを説明します:stackoverflow.com/a/43892905/960857
クリス

21

次のコードを変更します。

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

に:

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

その後、解決しました。


13

リストのレンダリングルートコンポーネントに小道具「キー」を追加します。

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

6

この警告は、リストアイテムにキーを追加しない場合に発生します。reactjsDocsによると-

キーは、Reactが変更、追加、または削除されたアイテムを識別するのに役立ちます。要素に安定したアイデンティティを与えるために、配列内の要素にキーを与える必要があります。

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

キーを選択する最良の方法は、兄弟の中でリストアイテムを一意に識別する文字列を使用することです。ほとんどの場合、データのIDをキーとして使用します。

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

レンダリングされたアイテムの安定したIDがない場合は、最後の手段としてアイテムインデックスをキーとして使用できます。

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

4

私はrenderSeparatorコンポーネントにプロパティを追加することでそれを修正しました。コードはここにあります:

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

この警告のキーワードは「一意」であり、sectionID + rowIDはListViewで一意の値を返します。


4

チェック:key = undef !!!

警告メッセージも表示されます。

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

コードが完全に正しい場合、ただしオンの場合

<MyComponent key={someValue} />

someValueは未定義です!!! 最初にこれを確認してください。時間を節約できます。


3

renderDetailItemメソッドに次の署名があると仮定します...

(rowData, sectionID, rowID, highlightRow) 

これをやってみてください...

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

3

これを修正するために使用した特定のコードは次のとおりです。

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

キーは一意である必要があるため、特定のコードを含めています。セパレーターの場合でも同様です。同様のことを行う場合、たとえばこれを定数に設定すると、キーの再利用に関して別の厄介なエラーが発生します。JSXがわからない場合は、JSへのコールバックを作成してさまざまな部分を実行するのは非常に面倒です。

そしてListViewで、明らかにこれを添付します:

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

この道を私に教えてくれたcoldbuffetとNaderDabitの功績です。


2

これは私の理解に基づいています。うまくいけば、それは役に立ちます。背後の例として、コンポーネントのリストをレンダリングすることになっています。各コンポーネントのルートタグには、が必要keyです。一意である必要はありません。それはすることはできませんkey=0key='0'などそれは鍵が役に立たないに見えます。

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

両方の条件が満たされているようです。おそらくkey( 'contact')が問題です

 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

この問題に私をつまずかせたのは、私が定義したJSX要素ではなく、「実際の」またはDOMHTML要素のように見えるものにキーを適用する必要があると思ったことです。

もちろん、Reactでは仮想DOMを使用しているため、定義するReact JSX要素は<MyElement>、実際のDOMHTML要素のように見える要素と同じくらい重要です。<div>です。

それは理にかなっていますか?


0

私の場合、Semantic UIReactの「カード」ビューを使用していました。作成した各カードにキーを追加すると、次のような警告は消えました。

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

-1

<Fade in>反応アプリケーションに要素を使用している場合は、その要素にもkey={}属性を追加してください。そうしないと、コンソールにエラーが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.