Функция видит старое значение в массиве состояний - PullRequest
0 голосов
/ 15 октября 2019

Я пытаюсь создать тестовое приложение, просто простую адресную книгу.

Я почти закончил, но сейчас у меня есть одна проблема с выбором элементов из 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>

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Здесь вы неоднозначно используете массив в качестве объекта:

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 всегда число?

0 голосов
/ 15 октября 2019

Реакт опирается на ссылки. Поэтому, когда вы изменяете свое состояние и затем пытаетесь установить его, ничего не происходит. Есть правило - государство должно быть неизменным. Попробуйте создать новый экземпляр вашего массива вместо того, чтобы изменить старый:

const newSelectedContacts = selectedContacts.slice();
newSelectedContacts[contact.id] = contact.facebook_url;

this.setState({selectedContacts: newSelectedContacts});

и ваш вызов .map() выглядит бесполезным - вы просто присваиваете одно и то же значение одному и тому же элементу массива несколько раз =)

...