警告:数组或迭代器中的每个子代都应具有唯一的“键”道具。检查`ListView`的渲染方法

我使用ReactNative为iOS和android 构建了一个带有的应用ListView当使用有效的数据源填充listview时,屏幕底部将显示以下警告:

警告:数组或迭代器中的每个子代都应具有唯一的“键”道具。检查的渲染方法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>
        );

Everything works fine and as expected, except the warning which seems to be complete nonsense to me.

Adding a key-property to my "DetailItem"-Class didn't solve the issue.

This is, what really will be passed to the ListView as a result of "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: 'xxxxxxxxx@hotmail.com',
I/ReactNativeJS( 1293):           headline: 'Email',
I/ReactNativeJS( 1293):           icon: 'fontawesome|envelope' },
I/ReactNativeJS( 1293):         { key: 6, type: 'moreInfo', text: '', headline: '', icon: '' } ] },

As one key see, each record has a key property. The warning still exists.

猴子樱2020/03/13 15:31:51

这一点不能足够强调:

键仅在周围数组的上下文中才有意义

“例如,如果提取ListItem组件,则应将键保留在数组的<ListItem />元素上,而不要保留在ListItem本身的<li>元素上。” - https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys

小胖蛋蛋2020/03/13 15:31:51

如果您将<Fade in>元素用于React应用程序,请key={}在其中添加属性,否则您将在控制台中看到错误。

飞云神乐2020/03/13 15:31:51

我用来解决此问题的特定代码是:

  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和Nader Dabit指出了我的这条路。

猿EvaL2020/03/13 15:31:51

检查:键= undef !!!

您还会收到警告消息:

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

如果您的代码是完整的正确的,但是如果

<MyComponent key={someValue} />

someValue未定义!!!请先检查一下。您可以节省时间。

神奇老丝2020/03/13 15:31:50

我通过向renderSeparator组件添加属性来修复它,代码在这里:

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

该警告的关键字是“唯一”,sectionID + rowID在ListView中返回唯一值。

路易伽罗2020/03/13 15:31:50

如果您未在列表项中添加键,则会出现此警告。根据react js Docs-

按键可帮助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>
);
Stafan小小2020/03/13 15:31:50

从以下位置更改代码:

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

然后解决。

斯丁小胖Jim2020/03/13 15:31:50

您还可以将迭代计数(i)用作key

render() {
    return (
      <ol>
        {this.props.results.map((result, i) => (
          <li key={i}>{result.text}</li>
        ))}
      </ol>
    );
}
伽罗GreenNear2020/03/13 15:31:50

我遇到了与您完全相同的问题已有一段时间,在查看了上面的一些建议后,我终于解决了问题。

事实证明(至少无论如何对我而言),我需要为要从renderSeparator方法返回的组件提供一个键(称为“键”的道具)。将密钥添加到我的renderRow或renderSectionHeader并没有做任何事情,但是将其添加到renderSeparator会使警告消失。

希望能有所帮助。