【问题标题】:React Native - Encountered two children with the same key, `221`React Native - 遇到两个孩子使用相同的键,`221`
【发布时间】:2021-10-29 20:40:04
【问题描述】:

我正在尝试通过 API 获取数据。数据以数组形式返回,我将其解析为 JSON,并在控制台日志中完美显示。但我无法在屏幕上显示,控制台显示以下警告,

警告:遇到两个孩子使用相同的密钥,221。键应该是唯一的,以便组件保持 他们在更新中的身份。非唯一键可能会导致子项重复和/或省略 - 该行为不受支持,并且可能会在未来版本中更改。

这是我的代码:

    import React from 'react';
    import { Container, Header, Title, Drawer, Content, Button, Left, Right, Body, Text} from 'native-base';
    import { Alert, View, TouchableOpacity, SafeAreaView } from 'react-native';
    import { MaterialIcons } from '@expo/vector-icons';
    import { Ionicons } from '@expo/vector-icons';
    import SideBar from './components/SideBar';
    import { FlatList } from 'react-native-gesture-handler';

    export default class QrScan extends React.Component{
    constructor(props) {
    super(props)

    this.state = {
        resourcedata:'',    
    };
    this.resourceAllocationList = this.resourceAllocationList.bind(this);       
    }

    closeDrawer = () => {
    this.drawer._root.close();
    }

    openDrawer = () => {
    this.drawer._root.open();
    }

    resourceAllocationList() {
    fetch('https://api.idepoz.com/ncl/api/getResource', {
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
    }).then((response) => response.json())
    .then((responseJson) => {
        if(responseJson)
        {
            var jsonData = JSON.stringify(responseJson.data);
            var resultdata = JSON.parse(jsonData);
            //console.log(resultdata);
            this.setState({resourcedata:resultdata});
        }
        
    }).catch((error) => {
        console.error(error);
    });
    }

    render()
    {
    const getHeader = () => {
        return <Text>{'Resource Allocation'}</Text>;
    };

    const getFooter = () => {
        if (this.state.loading) {
            return null;
        }
        return <Text>{'Loading...'}</Text>;
    };

    return(
        <Drawer
        ref={(ref) => { this.drawer = ref; }}
        content={<SideBar navigator={this.navigator} closeDrawer={this.closeDrawer} usertoken= 
        {this.props.navigation.state.params.usertoken} />}
        onClose={() => this.closeDrawer()} >
            <Container>
                <Header>
                    <Left>
                        <Button transparent onPress={this.openDrawer.bind(this)}>
                            <MaterialIcons name="list" size={40} color="#FFFFFF" />
                        </Button>
                    </Left>
                    <Body>
                        
                    </Body>
                    <Right>
                    <Button transparent>
                        <Ionicons  name="search" size={40} color="#FFFFFF" onPress={() => 
                        Alert.alert('Search Button pressed')} />
                    </Button>   
                    </Right>
                </Header>
                <Content>
                    <SafeAreaView style={{ 
                            flexDirection:"row",
                            justifyContent:'center',
                            marginTop: 20, 
                            alignItems: 'center',
                            marginHorizontal: 20,
                        }}>
                        
                        <TouchableOpacity onPress={this.resourceAllocationList}>
                            <Text>Press Here</Text>
                            <FlatList data={this.state.resourcedata}
                            renderItem={({ item }) => {
                                <Text>{ item.id }</Text>
                            }}
                            ListHeaderComponent={getHeader}
                            ListFooterComponent={getFooter}/>
                        </TouchableOpacity>
                        
                    </SafeAreaView>
                </Content>
            </Container>
        </Drawer>
        );
        }
        }

控制台返回数据如下:

数组 [ 目的 { “分配空间”:1, "created_at": "2021-03-26 15:49:55", “创建者”:1, “日期”:“2021-04-19”, “deleted_at”:空, “deleted_by”:空, “持续时间”:“01:00:00”, “employee_id”:2, "end_time": "01:05:00", “身份证”:73, “is_active”:1, "is_payable": 1, “order_plan_id”:1, “价格”:13, “资源分配ID”:73, “服务用户 ID”:1, "start_time": "00:05:00", “状态”:“已批准”, "updated_at": "2021-04-19 07:56:08", “updated_by”:1, }…………

谁能帮助如何在屏幕上返回上述数据?

【问题讨论】:

  • 我需要帮助,请如果有人可以回答!!!!!
  • {item.id} 这里的键必须是responseJson.data 中的某个唯一字段。如果可能的话,您的 item.id 可能是您应该使用的密钥
  • { item.id }改成key={item.id},还是一样的警告............遇到了两个具有相同密钥的孩子,221
  • Text key={item.key}> 不是 key={item.id}reactjs.org/docs/lists-and-keys.html
  • 我使用了@Hessuew 解决方案,它返回了一个KEYEXTRACTOR 问题,所以我在extradata 之后使用了“keyExtractor={(item, index) => 'key'+index}”......然后它返回另一个错误....“试图获取超出范围索引 NaN 的帧”........之后我在 this.state 中将 resourcedata 声明为数组并且没有解析其中的 responsejson。 setstate........现在没有错误或警告,但按下按钮后屏幕上什么也没有显示............怎么办???

标签: android react-native expo


【解决方案1】:

尝试将 extraData 属性添加到 Flatlist。
“通过将 extraData={selected} 传递给 FlatList,我们确保 FlatList 本身会在状态更改时重新渲染。如果不设置此道具,FlatList 将不知道它需要重新渲染任何项目,因为它是 PureComponent 和道具比较不会显示任何变化。” https://docs.expo.dev/versions/latest/react-native/flatlist/

如果您的数据中没有多个相同的 id,那么将“key”道具添加到您的 Flatlist Text 元素将消除错误。在这种情况下,您可以使用索引作为键,但这不是最佳做法。
因此,将您的平面列表更改为...

<FlatList
  data={this.state.resourcedata}
  extraData={this.state.resourcedata}
  renderItem={({ item }) => {
   <Text key={item.id}>{ item.id }</Text>
  }}
  ListHeaderComponent={getHeader}
  ListFooterComponent={getFooter
 />

我还使用了以下道具:initialNumToRender={8} windowSize={16} 来减少内存消耗,但这取决于您的用例和列表大小
更多关于 Flatlist 道具的信息:https://docs.expo.dev/versions/latest/react-native/flatlist/

(这是我第一次回答问题,请多多包涵)

编辑

如果在renderItem={}中使用了大括号{},则需要return()

keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => {  
 return (
   <Text key={index }>{ item.id }</Text>
  );
}}

否则,您可以在 renderItem 中使用普通大括号 (),看起来像...

keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (  
    <Text key={index}>{ item.id }</Text>
  )
}

我通常使用 {} 并返回,因为这样我什至可以将逻辑放在 return () 语句之前,例如 console.log()

【讨论】:

  • - 我使用了你的解决方案,它返回了一个 KEYEXTRACTOR 问题,所以我在 extradata 之后使用了 "keyExtractor={(item, index) => 'key'+index}" ......然后它返回另一个错误....“试图获取超出范围索引 NaN 的帧”........之后我在 this.state 中将 resourcedata 声明为数组并且没有解析其中的 responsejson。 setstate........现在没有错误或警告,但按下按钮后屏幕上没有显示任何内容............怎么办???
  • 如果在 rederItem 中使用大括号 {},则需要对 item 使用 return ()。抱歉,这个错误也在我的答案中,但现在我对其进行了编辑,因此显示正确的代码。
  • 如果我的回答解决了您的问题,请将其标记为正确答案:)
  • 没有错误了,但是屏幕上没有显示数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2017-12-15
  • 2017-05-17
  • 2021-06-24
  • 2021-03-08
  • 1970-01-01
  • 2018-10-06
相关资源
最近更新 更多