ReactNative警告:列表中的每个孩子都应该有一个唯一的“关键”道具

时间:2019-07-27 14:41:14

标签: reactjs react-native

我是本机新手,我正在编写包含卡片的应用平面列表,但出现此错误 这是我的代码

          constructor (props) {
        super(props);
        this.state = {
            GridListItems: [ // Home Screen Cards Data [STATIC]
              { id: 1 , key: "222" , img: 'https://i.ibb.co/Lt88dTg/makeup.png' },
               { id: 2 ,key: "2" , img: 'https://i.ibb.co/H4NRnZK/Photographers.png'},
               { id: 3 ,key: "Wedding Halls" , img: 'https://i.ibb.co/b2JdtHW/wedding-Hall.png'},
               { id: 4 ,key: "Wedding Planners" , img: 'https://i.ibb.co/g95HhKT/image-1.jpg'},
               { id: 5 ,key: "Ateliers for Dresses" , img: 'https://i.ibb.co/g4ksBDk/wedding.png'},
            ]
        };
    }
    renderItem = ({item}) => {
      return(
        <TouchableOpacity key={item.id.toString()}
        style={styles.GridViewContainer}
    >
      </TouchableOpacity>
      )

    }
render () {
  const carousel = this.mainCarousel(1); // Rendering the Carousel 

  return (
     <SafeAreaView style={styles.safeArea}>

    { this.gradient }
    <ScrollView
      style={styles.scrollview}
      scrollEventThrottle={200}
      directionalLockEnabled={true}
    >
        {/* { carousel }  */}

        <FlatList

        data={ this.state.GridListItems }
        keyExtractor={(item) => item.id.toString()}
        renderItem={ this.renderItem }
        numColumns={2}
        initialNumToRender={6}
/>
    </ScrollView>

</SafeAreaView>

);
}

但是我得到警告:列表中的每个孩子都应该有一个唯一的“键”道具。有关更多信息,请参见https://fb .me / react-warning-keys。%s,

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

检查是否可以解决问题:DateOfBirth3 如果不 , 使用它代替:  <form [formGroup]="profileForm" (ngSubmit)="onSubmit()"> <ion-card class="person1"> <ion-card-content class="padding-5"> <ion-list lines="full" class="ion-no-margin ion-no-padding"> <ion-item> <ion-label position="stacked">Name / Number <ion-text color="danger">*</ion-text> </ion-label> <ion-input type="text" formControlName="NameNumber"></ion-input> </ion-item> <ion-item> <ion-label position="stacked">Date of birth<ion-text color="danger">*</ion-text> </ion-label> <ion-datetime required placeholder="Select Date" formControlName="DateOfBirth"></ion-datetime> </ion-item> </ion-list> </ion-card-content> </ion-card> <ion-card class="person2" *ngIf="isComparisonChecked"> <ion-card-content class="padding-5"> <ion-list lines="full" class="ion-no-margin ion-no-padding"> <ion-item> <ion-label position="stacked">Name / Number <ion-text color="danger">*</ion-text> </ion-label> <ion-input type="text" formControlName="NameNumber2"></ion-input> </ion-item> <ion-item> <ion-label position="stacked">Date of birth<ion-text color="danger">*</ion-text> </ion-label> <ion-datetime required placeholder="Select Date" formControlName="DateOfBirth2"></ion-datetime> </ion-item> </ion-list> </ion-card-content> </ion-card> <ion-card class="person3" *ngIf="isComparisonChecked"> <ion-card-content class="padding-5"> <ion-list lines="full" class="ion-no-margin ion-no-padding"> <ion-item> <ion-label position="stacked">Name / Number <ion-text color="danger">*</ion-text> </ion-label> <ion-input type="text" formControlName="NameNumber3"></ion-input> </ion-item> <ion-item> <ion-label position="stacked">Date of birth<ion-text color="danger">*</ion-text> </ion-label> <ion-datetime required placeholder="Select Date" formControlName="DateOfBirth3"></ion-datetime> </ion-item> </ion-list> </ion-card-content> </ion-card> <ion-item class="compare-section" lines="none"> <ion-label>Compare</ion-label> <ion-checkbox color="danger" checked="false" formControlName="IsCompare"></ion-checkbox> </ion-item> <div class="ion-padding"> <ion-row> <ion-col> <ion-button color="secondary" expand="block" type="button" (click)="resetForm()" class="ion-no-margin">Clear </ion-button> </ion-col> <ion-col> <ion-button color="danger" [disabled]="!this.profileForm.valid" expand="block" type="submit" class="ion-no-margin">Submit</ion-button> </ion-col> </ion-row> </div> </form> $ {index} ... profileForm = new FormGroup({ NameNumber: new FormControl('', [Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]), DateOfBirth: new FormControl('', Validators.required), IsCompare: new FormControl(false) }); ... ngOnInit() { this.profileForm.get('IsCompare').valueChanges.subscribe(checked => { this.isComparisonChecked = checked; if (checked) { this.profileForm.addControl('NameNumber2', new FormControl('', [Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')])); this.profileForm.addControl('DateOfBirth2', new FormControl('', Validators.required)); this.profileForm.get('NameNumber2').valueChanges.subscribe(() => { if (this.profileForm.get('NameNumber2').valid) { this.profileForm.get('DateOfBirth2').clearValidators(); } else { this.profileForm.get('DateOfBirth2').setValidators([Validators.required]); } this.profileForm.get('DateOfBirth2').updateValueAndValidity({ emitEvent: false }); }); this.profileForm.get('DateOfBirth2').valueChanges.subscribe(() => { if (this.profileForm.get('DateOfBirth2').valid) { this.profileForm.get('NameNumber2').clearValidators(); } else { this.profileForm.get('NameNumber2').setValidators([Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]); } this.profileForm.get('NameNumber2').updateValueAndValidity({ emitEvent: false }); }); this.profileForm.addControl('NameNumber3', new FormControl('', [Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')])); this.profileForm.addControl('DateOfBirth3', new FormControl('', Validators.required)); this.profileForm.get('NameNumber3').valueChanges.subscribe(() => { if (this.profileForm.get('NameNumber3').valid) { this.profileForm.get('DateOfBirth3').clearValidators(); } else { this.profileForm.get('DateOfBirth3').setValidators([Validators.required]); } this.profileForm.get('DateOfBirth3').updateValueAndValidity({ emitEvent: false }); }); this.profileForm.get('DateOfBirth3').valueChanges.subscribe(() => { if (this.profileForm.get('DateOfBirth3').valid) { this.profileForm.get('NameNumber3').clearValidators(); } else { this.profileForm.get('NameNumber3').setValidators([Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]); } this.profileForm.get('NameNumber3').updateValueAndValidity({ emitEvent: false }); }); } else { this.profileForm.removeControl('NameNumber2'); this.profileForm.removeControl('DateOfBirth2'); this.profileForm.removeControl('NameNumber3'); this.profileForm.removeControl('DateOfBirth3'); } });

keyExtractor={({item, index}) => item.id.toString()}

答案 1 :(得分:1)

我会在keyExtractor中创建console.log语句,以查看您得到了什么:

keyExtractor={(item, index) => {
  console.log('item', item);
  return item.id.toString();
}}

这样,您可以查看将什么数据传递到函数中并返回相关部分。

顺便说一句:Flatlist是可滚动的列表,因此您无需将其包装在ScrollView中。参见https://facebook.github.io/react-native/docs/flatlist