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

IT技术 facebook listview reactjs react-native
2021-04-16 00:59:19

我使用ReactNative为 iOS 和 android构建了一个应用程序,并带有ListView. 使用有效数据源填充列表视图时,屏幕底部会打印以下警告:

警告:数组或迭代器中的每个孩子都应该有一个唯一的“键”props。检查 的渲染方法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: '' } ] },

正如一个键所见,每条记录都有一个键属性。警告仍然存在。

6个回答

我已经和你遇到了完全相同的问题一段时间了,在查看了上面的一些建议之后,我终于解决了这个问题。

事实证明(至少对我而言),我需要为我从 renderSeparator 方法返回的组件提供一个键(一个名为“key”的props)。向我的 renderRow 或 renderSectionHeader 添加一个键没有做任何事情,但是将它添加到 renderSeparator 会使警告消失。

希望有帮助。

在阅读本文之前,我浪费了大约 8 个小时来跟踪我认为 JSON 数据存在的问题。如果有堆栈溢出 :taco: 我会给你一个!
2021-05-28 00:59:19
就我而言,我只是删除了 renderSeparator 并将我的 <Separator> 移到了 renderRow 返回值的主体中。
2021-06-14 00:59:19
对于SectionList这里也有同样的事情,必须为每个显式添加一个带有名称的属性,item以使 RN 满意。
2021-06-16 00:59:19

您需要提供密钥

如果您有一个关键属性,请尝试在您的 ListView Rows 中执行此操作:

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

如果没有,请尝试将项目添加为键:

<TouchableHighlight key={item} underlayColor='#dddddd'>
我更喜欢这个答案,因为它有代码,所以我可以复制 XD
2021-06-03 00:59:19
这个答案有点改变了我对语言的理解。我特别认为我不能这样做,所以我不确定如何继续。现在我明白了,看起来像 HTML 的代码只是另一种语法,它不是要呈现的内容,它只是更容易阅读。
2021-06-04 00:59:19

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

render() {
    return (
      <ol>
        {this.props.results.map((result, i) => (
          <li key={i}>{result.text}</li>
        ))}
      </ol>
    );
}
当数组更改时,这可能不起作用。这个答案用一个例子来解释它:stackoverflow.com/a/43892905/960857
2021-06-04 00:59:19

更改您的代码:

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

然后解决了。

向列表的渲染根组件添加一个 prop 'key'。

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