React Native - 遇到两个孩子使用相同的键,`221`

Posted

技术标签:

【中文标题】React Native - 遇到两个孩子使用相同的键,`221`【英文标题】:React Native - Encountered two children with the same key, `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........现在没有错误或警告,但按下按钮后屏幕上什么也没有显示............怎么办??? 【参考方案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 ()。抱歉,这个错误也在我的答案中,但现在我对其进行了编辑,因此显示正确的代码。 如果我的回答解决了您的问题,请将其标记为正确答案:) 没有错误了,但是屏幕上没有显示数据

以上是关于React Native - 遇到两个孩子使用相同的键,`221`的主要内容,如果未能解决你的问题,请参考以下文章

react native routerflux 遇到两个key相同的child

React Native - 将父母的状态传递给孩子的麻烦

警告:遇到两个孩子使用相同的钥匙

React组件中两个具有相同键的孩子

Flex React Native FlatList 孩子长到全高?

React-Native '不能将没有 YogaNode 的孩子添加到没有测量功能的父母!