gpt4 book ai didi

react-native - 我如何解决这个 : Warning: Encountered two children with the same key, `%s`

转载 作者:行者123 更新时间:2023-12-04 05:14:34 33 4
gpt4 key购买 nike

我是 react-native 的新手,这不是我编写这个应用程序的人。

有人能帮我解决这个错误吗,我认为是平面列表导致了这个错误,因为只有我加载页面或搜索列表中的内容才会发生这种情况。我知道有很多关于这个错误的问题,但我没有找到适合我的解决方案。
Warning: Encountered two children with the same key, %s . Keys should be unique so that components maintain their identity across updates.
ContactScreen.js

import React from 'react';
import { Button, View, FlatList, Alert, StyleSheet, KeyboardAvoidingView } from 'react-native';
import { ListItem, SearchBar } from 'react-native-elements';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { Contacts } from 'expo';
import * as Api from '../rest/api';
import theme from '../styles/theme.style';
import { Contact, ContactType } from '../models/Contact';

class ContactsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: "Contacts",
headerRight: (
<Button
onPress={() => navigation.popToTop()}
title="Déconnexion"
/>
),
}
};

constructor(props) {
super(props);

this.state = {
contacts: [],
search: '',
isFetching: false,
display_contacts: []
}
}

async componentDidMount() {
this.getContactsAsync();
}

async getContactsAsync() {
const permission = await Expo.Permissions.askAsync(Expo.Permissions.CONTACTS);
if (permission.status !== 'granted') { return; }

const contacts = await Contacts.getContactsAsync({
fields: [
Contacts.PHONE_NUMBERS,
Contacts.EMAILS,
Contacts.IMAGE
],
pageSize: 100,
pageOffset: 0,
});


const listContacts = [];
if (contacts.total > 0) {
for(var i in contacts.data) {
let contact = contacts.data[i];
let id = contact.id;
let first_name = contact.firstName;
let middle_name = contact.middleName;
let last_name = contact.lastName;
let email = "";
if ("emails" in contact && contact.emails.length > 0) {
email = contact.emails[0].email;
}
let phone = "";
if ("phoneNumbers" in contact && contact.phoneNumbers.length > 0) {
phone = contact.phoneNumbers[0].number;
}
listContacts.push(new Contact(id, first_name, middle_name, last_name, email, phone, ContactType.UP));
}
}

const soemanContacts = await Api.getContacts();
if (soemanContacts.length > 0) {
for(var i in soemanContacts) {
let contact = soemanContacts[i];
let id = contact.contact_id.toString();
let first_name = contact.contact_first_name
let last_name = contact.contact_last_name;
let email = contact.contact_email;
let phone = contact.contact_phone.toString();
listContacts.push(new Contact(id, first_name, "", last_name, email, phone, ContactType.DOWN));
}
}

listContacts.sort((a, b) => a.name.localeCompare(b.name));
this.setState({contacts: listContacts});
this.setState({ isFetching: false });
this.updateSearch(null);
}

async addContactAsync(c) {
const contact = {
[Contacts.Fields.FirstName]: c.firstName,
[Contacts.Fields.LastName]: c.lastName,
[Contacts.Fields.phoneNumbers]: [
{
'number': c.phone
},
],
[Contacts.Fields.Emails]: [
{
'email': c.email
}
]
}
const contactId = await Contacts.addContactAsync(contact);
}

onRefresh() {
this.setState({ isFetching: true }, function() { this.getContactsAsync() });
}

updateSearch = search => {
this.setState({ search });
if(!search) {
this.setState({display_contacts: this.state.contacts});
}
else {

const res = this.state.contacts.filter(contact => contact.name.toLowerCase().includes(search.toLowerCase()));
console.log(res);
this.setState({display_contacts: res});
console.log("contact display "+ this.state.display_contacts);
}
};

toggleContact(contact) {
switch(contact.type) {
case ContactType.SYNC:
break;
case ContactType.DOWN:
this.addContactAsync(contact);
break;
case ContactType.UP:
Api.addContact(contact);
break;
}
/*Alert.alert(
'Synchronisé',
contact.name + 'est déjà synchronisé'
);*/
}

renderSeparator = () => (
<View style={{ height: 0.5, backgroundColor: 'grey', marginLeft: 0 }} />
)

render() {
return (
<View style={{ flex: 1 }}>
<KeyboardAvoidingView style={{ justifyContent: 'flex-end' }} behavior="padding" enabled>
<SearchBar
platform="default"
lightTheme={true}
containerStyle={styles.searchBar}
inputStyle={styles.textInput}
placeholder="Type Here..."
onChangeText={this.updateSearch}
value={this.state.search}
clearIcon
/>
<FlatList
data={this.state.display_contacts}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
renderItem={this.renderItem}
keyExtractor={contact => contact.id}
ItemSeparatorComponent={this.renderSeparator}
ListEmptyComponent={this.renderEmptyContainer()}
/>
</KeyboardAvoidingView>
</View>
);
}

renderItem = (item) => {
const contact = item.item;
let icon_name = '';
let icon_color = 'black';
switch(contact.type) {
case ContactType.SYNC:
icon_name = 'ios-done-all';
icon_color = 'green';
break;
case ContactType.DOWN:
icon_name = 'ios-arrow-down';
break;
case ContactType.UP:
icon_name = 'ios-arrow-up';
break;
}
return (
<ListItem
onPress={ () => this.toggleContact(contact) }
roundAvatar
title={contact.name}
subtitle={contact.phone}
//avatar={{ uri: item.avatar }}
containerStyle={{ borderBottomWidth: 0 }}
rightIcon={<Ionicons name={icon_name} size={20} color={icon_color}/>}
/>
);
}

renderEmptyContainer() {
return (
<View>
</View>
)
}
}

const styles = StyleSheet.create({
searchBar: {
backgroundColor: theme.PRIMARY_COLOR
},
textInput: {
backgroundColor: theme.PRIMARY_COLOR,
color: 'white'
}
});

export default ContactsScreen;


我在这个应用程序中使用了 react-native 和 expo。

最佳答案

不要使用索引即时构建键。如果要构建 key ,则应尽可能在渲染之前进行。

如果您的联系人有保证的唯一 ID,您应该使用它。如果没有,您应该在数据出现在 View 中之前使用生成唯一键的函数构建一个键

示例代码:

  // Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
const keyGenerator = () => '_' + Math.random().toString(36).substr(2, 9)
// in component
key={contact.key}

关于react-native - 我如何解决这个 : Warning: Encountered two children with the same key, `%s`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55651942/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com