Firebase 错误:警告:数组或迭代器中的每个子级都应具有唯一的;“关键”;prop.%s%s使用平面列表(React Native)

Firebase 错误:警告:数组或迭代器中的每个子级都应具有唯一的;“关键”;prop.%s%s使用平面列表(React Native),firebase,react-native,google-cloud-firestore,infinite-scroll,Firebase,React Native,Google Cloud Firestore,Infinite Scroll,我正在使用Cloud Firestore实现无限滚动,并使用lastVisible作为文档引用,以了解在何处为另外5个用户进行刷新查询(限制设置为5) 我让keyExtractor使用item.id,但仍然返回错误警告:数组或迭代器中的每个子级都应该有一个唯一的“key”属性。%s%s,即使我正在为keyExtractor使用item.id keyExtractor={(item) => { item.id; }} 我还尝试从stackoverflow上的一篇文章中使用item.id

我正在使用Cloud Firestore实现无限滚动,并使用lastVisible作为文档引用,以了解在何处为另外5个用户进行刷新查询(限制设置为5)

我让keyExtractor使用item.id,但仍然返回错误警告:数组或迭代器中的每个子级都应该有一个唯一的“key”属性。%s%s,即使我正在为keyExtractor使用item.id

keyExtractor={(item) => {
  item.id;
}}
我还尝试从stackoverflow上的一篇文章中使用item.id.toString(),但这也不起作用

// Imports: Dependencies
import React, { Component } from "react";
import { ActivityIndicator, Dimensions, FlatList, View, SafeAreaView, ScrollView, StyleSheet, Text, TouchableOpacity } from 'react-native';
import * as firebase from 'firebase';
import 'firebase/firestore';
import firebaseConfig from '../config/config';

// Imports: Components
import UserSelector from '../components/UserSelector';
import TitleLarge from '../components/TitleLarge';

// Screen Dimensions
const { height, width } = Dimensions.get('window');

// Screen: Flat List (Users)
class FlatListUsers extends Component {
  constructor(props) {
    super(props);

    this.state = {
      data: [],
      limit: 5,
      lastVisible: null,
      loading: false,
      refreshing: false,
    };
  }

  // Component Will Mount
  componentWillMount = () => {
    // Firebase: Initialize
    firebase.initializeApp({
      apiKey: `${firebaseConfig.apiKey}`,
      authDomain: `${firebaseConfig.authDomain}`,
      databaseURL: `${firebaseConfig.databaseURL}`,
      projectId: `${firebaseConfig.projectId}`,
      storageBucket: `${firebaseConfig.storageBucket}`,
      messagingSenderId: `${firebaseConfig.messagingSenderId}`,
    });
  }

  // Component Did Mount
  componentDidMount = () => {
    this.retrieveUsers();
  }

  // Retrieve Users
  retrieveUsers = async () => {
    try {
      // Set State: Loading
      this.setState({ loading: true });

      // Firebase: Database + Settings
      const db = firebase.firestore();

      // Query
      console.log('Fetching Users')
      const initialQuery = await db.collection('users')
                        .where('company', '==', 'Google')
                        .orderBy('first_name')
                        .limit(this.state.limit);

      // Query Snapshot
      const querySnapshot = await initialQuery.get();

      // Document Data
      console.log('Document Data');
      const documentData = querySnapshot.docs.map(document => document.data());
      console.log(documentData);

      // Last Visible Document
      let lastVisible = documentData[documentData.length - 1];

      // Set State
      await this.setState({
        data: documentData,
        lastVisible: lastVisible,
        loading: false,
        refreshing: false,
      });

      console.log('Last Visible');
      console.log(typeof this.state.lastVisible)
      console.log(JSON.stringify(this.state.lastVisible))
    }
    catch (error) {
      console.log(error);
    }
  };

  // Retrieve More Users
  retrieveMore = async () => {
    try {
      const { lastVisible } = this.state;

      console.log('Retrieving more Users (Retrieve More)');
      this.setState({ loading: true });
      await console.log(`Last Visible (Retrieve More): ${this.state.lastVisible}`);

      // Firebase: Database + Settings
      const db = firebase.firestore();

      // Query
      console.log('Paginated Query starting (Retrieve More)');
      const paginatedQuery = await db.collection('licenses')
                        .where('company', '==', 'Google')
                        .orderBy('first_name')
                        .startAfter(lastVisible)
                        .limit(this.state.limit)

      // Query Snapshot
      const querySnapshot = await paginatedQuery.get();
      console.log(`Query Snapshot (Retrieve More): ${querySnapshot}`);

      // Document Data
      const documentData = querySnapshot.docs.map(document => document.data());
      console.log(`Document Data (Retrieve More): ${documentData}`);

      // Last Visible Document (Used As Query Position)
      let lastVisible = documentData[documentData.length - 1];
      console.log(`Last Visible New (Retrieve More): ${lastVisible}`);

      // Set State
      this.setState({
          data: [...this.state.data, ...documentData],
          lastVisible: lastVisible,
          loading: false,
          refreshing: false,
      });
    }
    catch (error) {
      console.log(error);
    }
  };

  // Render Header
  renderHeader = () => {
    try {
      return (
        <TitleLarge title="Users" />
      )
    }
    catch (error) {
      console.log(error);
    }
  };

  // Render Footer
  renderFooter = () => {
    try {
      // Check If Loading
      if (this.state.loading) {
        return (
          <View style={styles.activityIndicator}>
            <ActivityIndicator />
          </View>
        )
      }
      else {
        return null;
      }
    }
    catch (error) {
      console.log(error);
    }
  };

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <FlatList
          data={this.state.data}
          renderItem={({ item }) => ( 
            <UserSelector
              key={(item, index) => {
                return item.id;
              }}
              firstName={item.first_name}
              lastName={item.last_name}
              company={item.company}
            />
          )}
          keyExtractor={(item) => {
            item.id;
          }}
          ListHeaderComponent={this.renderHeader}
          ListFooterComponent={this.renderFooter}
          onEndReached={()=>{
            if (this.state.loading === false) {
             this.retrieveMore();
            }
          }}          
          onEndReachedThreshold={0}
        />
      </SafeAreaView>
    )
  }
}

// Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    height: height,
    width: width,
    borderTopWidth: 0,
    borderBottomWidth: 0,
  },
  scrollView:{
    height: 'auto',
  },
  UserContainer: {
    width: width,
    marginBottom: 7,
  },
  itemText: {
    fontFamily: 'System',
    fontSize: 17,
    fontWeight: '400',
    color: '#222222',
    marginLeft: 16,
  },
  activityIndicator: {
    paddingVertical: 20,
    borderTopWidth: 0,
    borderTopColor: '#CED0CE',
  },
});

// Exports
export default FlatListUsers
//导入:依赖项
从“React”导入React,{Component};
从“react native”导入{ActivityIndicator,Dimensions,FlatList,View,SafeAreaView,ScrollView,StyleSheet,Text,TouchableOpacity};
从“firebase”导入*作为firebase;
导入“firebase/firestore”;
从“../config/config”导入firebaseConfig;
//进口:组件
从“../components/UserSelector”导入UserSelector;
从“../components/TitleLarge”导入标题栏;
//屏幕尺寸
const{height,width}=Dimensions.get('window');
//屏幕:平面列表(用户)
类FlatListUsers扩展组件{
建造师(道具){
超级(道具);
此.state={
数据:[],
限额:5,
lastVisible:null,
加载:false,
刷新:错,
};
}
//组件将安装
组件将装入=()=>{
//Firebase:初始化
firebase.initializeApp({
apiKey:`${firebaseConfig.apiKey}`,
authDomain:`${firebaseConfig.authDomain}`,
databaseURL:`${firebaseConfig.databaseURL}`,
projectId:`${firebaseConfig.projectId}`,
storageBucket:`${firebaseConfig.storageBucket}`,
messagingSenderId:“${firebaseConfig.messagingSenderId}”,
});
}
//组件没有安装
componentDidMount=()=>{
this.retrieveUsers();
}
//检索用户
retrieveUsers=async()=>{
试一试{
//设置状态:加载
this.setState({loading:true});
//Firebase:数据库+设置
const db=firebase.firestore();
//质疑
console.log('Fetching Users')
const initialQuery=await db.collection('用户')
.where('company','=','Google')
.orderBy('first_name')
.limit(此.state.limit);
//查询快照
const querySnapshot=wait initialQuery.get();
//文件数据
console.log(“文档数据”);
const documentData=querySnapshot.docs.map(document=>document.data());
控制台日志(文档数据);
//最后可见文档
让lastVisible=documentData[documentData.length-1];
//设定状态
等待这一天({
数据:文档数据,
lastVisible:lastVisible,
加载:false,
刷新:错,
});
console.log(“最后可见”);
console.log(this.state.lastVisible的类型)
log(JSON.stringify(this.state.lastVisible))
}
捕获(错误){
console.log(错误);
}
};
//检索更多用户
retrieveMore=async()=>{
试一试{
const{lastVisible}=this.state;
log('检索更多用户(检索更多用户)';
this.setState({loading:true});
wait console.log(`Last Visible(Retrieve More):${this.state.lastVisible}`);
//Firebase:数据库+设置
const db=firebase.firestore();
//质疑
log('分页查询开始(检索更多)';
const paginatedQuery=wait db.collection('许可证')
.where('company','=','Google')
.orderBy('first_name')
.startAfter(最后可见)
.limit(此.state.limit)
//查询快照
const querySnapshot=wait paginatedQuery.get();
log(`querySnapshot(检索更多):${querySnapshot}`);
//文件数据
const documentData=querySnapshot.docs.map(document=>document.data());
log(`documentData(检索更多):${documentData}`);
//最后可见文档(用作查询位置)
让lastVisible=documentData[documentData.length-1];
log(`Last Visible New(Retrieve More):${lastVisible}`);
//设定状态
这是我的国家({
数据:[…this.state.data,…documentData],
lastVisible:lastVisible,
加载:false,
刷新:错,
});
}
捕获(错误){
console.log(错误);
}
};
//渲染头
renderHeader=()=>{
试一试{
返回(
)
}
捕获(错误){
console.log(错误);
}
};
//渲染页脚
renderFooter=()=>{
试一试{
//检查是否已加载
if(this.state.loading){
返回(
)
}
否则{
返回null;
}
}
捕获(错误){
console.log(错误);
}
};
render(){
返回(
( 
{
返回item.id;
}}
firstName={item.first_name}
lastName={item.last_name}
公司={item.company}
/>
)}
keyExtractor={(项目)=>{
项目id;
}}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
onEndReached={()=>{
if(this.state.loading==false){
这个。retrieveMore();
}
}}          
onEndReachedThreshold={0}
/>
)
}
}
//风格
const styles=StyleSheet.create({
容器:{
弹性:1,
为内容辩护:“中心”,
高度:高度,,
宽度:宽度,
borderTopWidth:0,
边框底部宽度:0,
},
滚动视图:{
高度:“自动”,
},
用户容器:{
宽度:宽度,
马金贝托姆
keyExtractor={(item) => {
  return item.id.toString()
}}
keyExtractor={(item) => item.id.toString()}
keyExtractor={(item, index) => String(index)}
            <FlatList
                            data={this.state.data}
                            renderItem={({ item }) => (
                                <UserSelector
                                    key={(item, index) => {
                                        return item.id;
                                    }}
                                    firstName={item.first_name}
                                    lastName={item.last_name}
                                    company={item.company}
                                />
                            )}
                            keyExtractor={(item) => {
                                item.id;
                            }}
                            ListHeaderComponent={this.renderHeader}
                            ListFooterComponent={this.renderFooter}
                            keyExtractor={(item, index) => String(index)}
                            onEndReached={() => {
                                if (this.state.loading === false) {
                                    this.retrieveMore();
                                }
                            }}
                            onEndReachedThreshold={0}
                        />
keyExtractor tells the list to use the ids for the react keys instead of the default key property.