函数在状态数组上看到旧值
Function sees old value on state array
我正在尝试制作测试应用程序,只是一个简单的地址簿。
我快完成了,但现在我在从 FlatList 中选择项目时遇到了一个问题。
当我长按一个联系人时,它会触发 onLongPress 函数,它将该联系人标记为已选中,并使用 this.setState({selectedContacts})
保存已选中联系人的列表
问题是当我点击一个联系人时,如果已经选择了一个联系人,它应该继续选择,如果没有选择联系人,它应该进入那个联系人详细信息屏幕。
问题在于 onPress 函数 this.state.selectedContacts.length
始终为 0。
onPress(contact) {
console.log("Contacts Selected:",this.state.selectedContacts.length);
if (this.state.selectedContacts.length < 1) {
console.log("navigating");
this.props.navigation.navigate('ContactDetails', {
id: `${contact.id}`,
});
} else {
this.toggleSelection(contact);
}
console.log("onPress",this.state.selectedContacts);
}
onLongPress(contact) {
toggleSelection(contact);
console.log("onLongPress",this.state.selectedContacts);
}
toggleSelection(contact) {
contact.isSelected = !contact.isSelected;
selectedContacts = [];
this.state.contacts.map(function(contact){
if (contact.isSelected){
selectedContacts[contact.id] = contact.facebook_url;
}
});
this.setState({selectedContacts});
}
<TouchableOpacity style={listItemStyle}
onPress={() => this.onPress(contact)}
onLongPress={() => this.onLongPress(contact)}>
<Image source={{ uri: contact.icon }} style={styles.itemListAvatar} />
<View style={styles.itemListText}>
<Text style={styles.itemListName}>
{contact.name}
</Text>
<Text style={styles.itemListDescription}>
{contact.description}
</Text>
</View>
</TouchableOpacity>
React 依赖于引用。所以,当你改变你的状态然后尝试设置它时,什么也不会发生。有一条规则——状态应该是不可变的。尝试创建数组的新实例而不是改变旧实例:
const newSelectedContacts = selectedContacts.slice();
newSelectedContacts[contact.id] = contact.facebook_url;
this.setState({selectedContacts: newSelectedContacts});
你的 .map()
调用看起来也没什么用 - 你只是多次将相同的值分配给同一个数组项 =)
你在这里含糊地使用数组作为对象:
toggleSelection(contact) {
contact.isSelected = !contact.isSelected;
selectedContacts = [];
this.state.contacts.map(function(contact){
if (contact.isSelected){
selectedContacts[contact.id] = contact.facebook_url;
}
});
this.setState({selectedContacts});
}
要将项目添加到 javascript 数组,您必须使用 Array.prototype.push 方法,否则长度不会改变(不完全正确,详情如下)。
事情是 JS typeof [] === 'object
所以你可以写 arr[newKeyThatMayNotBeANumber] 来添加 newKeyThatMayNotBeANumber
属性 到 arr 对象,但是这样做,你不会总是增加数组长度。
因为JS太善良了,如果newKeyThatMayNotBeANumber
可以解释为数字(即:是一个数字,或者一个数字的base10字符串表示),它实际上会改变数组的大小。
但否则它会失败。因此,使用实际对象({}
)进行键寻址,使用数组变异方法(或严格的数字索引访问)是一个好习惯。
Chrome 中的控制台输出演示了此类问题:
const arr = [];
console.log(arr.length)
=> 0
arr['128'] = 'a';
console.log(arr)
=> [empty × 128, "a"]
console.log(arr.length)
=> 129
arr['bar'] = 'a';
console.log(arr)
=> (129) [empty × 128, "a", bar: "a"]
console.log(arr.length)
=> 129
也就是说,contact.id 总是一个数字吗?
我正在尝试制作测试应用程序,只是一个简单的地址簿。
我快完成了,但现在我在从 FlatList 中选择项目时遇到了一个问题。
当我长按一个联系人时,它会触发 onLongPress 函数,它将该联系人标记为已选中,并使用 this.setState({selectedContacts})
问题是当我点击一个联系人时,如果已经选择了一个联系人,它应该继续选择,如果没有选择联系人,它应该进入那个联系人详细信息屏幕。
问题在于 onPress 函数 this.state.selectedContacts.length
始终为 0。
onPress(contact) {
console.log("Contacts Selected:",this.state.selectedContacts.length);
if (this.state.selectedContacts.length < 1) {
console.log("navigating");
this.props.navigation.navigate('ContactDetails', {
id: `${contact.id}`,
});
} else {
this.toggleSelection(contact);
}
console.log("onPress",this.state.selectedContacts);
}
onLongPress(contact) {
toggleSelection(contact);
console.log("onLongPress",this.state.selectedContacts);
}
toggleSelection(contact) {
contact.isSelected = !contact.isSelected;
selectedContacts = [];
this.state.contacts.map(function(contact){
if (contact.isSelected){
selectedContacts[contact.id] = contact.facebook_url;
}
});
this.setState({selectedContacts});
}
<TouchableOpacity style={listItemStyle}
onPress={() => this.onPress(contact)}
onLongPress={() => this.onLongPress(contact)}>
<Image source={{ uri: contact.icon }} style={styles.itemListAvatar} />
<View style={styles.itemListText}>
<Text style={styles.itemListName}>
{contact.name}
</Text>
<Text style={styles.itemListDescription}>
{contact.description}
</Text>
</View>
</TouchableOpacity>
React 依赖于引用。所以,当你改变你的状态然后尝试设置它时,什么也不会发生。有一条规则——状态应该是不可变的。尝试创建数组的新实例而不是改变旧实例:
const newSelectedContacts = selectedContacts.slice();
newSelectedContacts[contact.id] = contact.facebook_url;
this.setState({selectedContacts: newSelectedContacts});
你的 .map()
调用看起来也没什么用 - 你只是多次将相同的值分配给同一个数组项 =)
你在这里含糊地使用数组作为对象:
toggleSelection(contact) {
contact.isSelected = !contact.isSelected;
selectedContacts = [];
this.state.contacts.map(function(contact){
if (contact.isSelected){
selectedContacts[contact.id] = contact.facebook_url;
}
});
this.setState({selectedContacts});
}
要将项目添加到 javascript 数组,您必须使用 Array.prototype.push 方法,否则长度不会改变(不完全正确,详情如下)。
事情是 JS typeof [] === 'object
所以你可以写 arr[newKeyThatMayNotBeANumber] 来添加 newKeyThatMayNotBeANumber
属性 到 arr 对象,但是这样做,你不会总是增加数组长度。
因为JS太善良了,如果newKeyThatMayNotBeANumber
可以解释为数字(即:是一个数字,或者一个数字的base10字符串表示),它实际上会改变数组的大小。
但否则它会失败。因此,使用实际对象({}
)进行键寻址,使用数组变异方法(或严格的数字索引访问)是一个好习惯。
Chrome 中的控制台输出演示了此类问题:
const arr = [];
console.log(arr.length)
=> 0
arr['128'] = 'a';
console.log(arr)
=> [empty × 128, "a"]
console.log(arr.length)
=> 129
arr['bar'] = 'a';
console.log(arr)
=> (129) [empty × 128, "a", bar: "a"]
console.log(arr.length)
=> 129
也就是说,contact.id 总是一个数字吗?