Сортировка телефонных контактов с React Native - PullRequest
0 голосов
/ 10 марта 2020

Мое приложение реагирует на родство, отправляет что-то похожее на сообщения контактам в телефонной книге пользователя, в которой есть мое приложение. Поэтому, когда пользователи регистрируются, они регистрируются только для использования моего приложения, они регистрируют только свой номер телефона. Когда дело доходит до отправки сообщения контакту. Я получаю доступ к их телефонной книге и сравниваю ее с номерами, которые есть у меня в Rails. Если они совпадают с номером в телефонной книге пользователя. Затем я извлекаю имя из их телефонной книги и отображаю его вместе с номером, чтобы отправить сообщение этому контакту.

Проблема в том, что они сортируются случайным образом. Я хочу, чтобы они сортировали по алфавиту. Номер взят из BE (Rails), а имя - из приложения FE (React-Native). Я знаю, что мне нужно поместить их обоих в какой-то массив в FE, а затем отсортировать их. К сожалению, мои навыки Javascript и React-Native все еще несколько слабы. Теоретически я знаю, что мне нужно делать, но я просто не могу заставить его работать.

Я, конечно, оставил довольно много кода и оставил только важные части. В первой части показаны три функции: "parseContacts, fetchContacts, getContactName.

" fetchContacts "получает номер телефона от BE." GetContactName "получает имя из телефонных книг телефонов." ParseContacts "делает то, о чем говорит жесть.

async parseContacts(contacts) {
    let numbers = [];
    contacts.forEach(element => {
      element.contactNumber = element.phoneNumbers[0] ? element.phoneNumbers[0].number.replace(/[^a-zA-Z0-9]/g, '') : '';
      element.phoneNumbers[0] ? numbers.push(element.phoneNumbers[0].number.replace(/[^a-zA-Z0-9]/g, '')) : null;
    });
    this.setState({ phoneContacts: contacts })
    return numbers;
  }

  async fetchContacts(contacts) {
    let phoneNumbers = await this.parseContacts(contacts);
    if (phoneNumbers.length) {
      this.setState({ isLoadingNumbers: true })
      let data = {
        "numbers": phoneNumbers,
      }
      try {
        let res = await postFunctionWithAuthToken(`${baseUrl}/contact/check`,
          JSON.stringify(data), this.state.authToken);
        if (res.response) {
          console.log('contacssssst: ', res.contact_list);
          this.setState({ contacts: res.contact_list, isLoadingNumbers: false })
        } else {
          this.setState({ isLoadingNumbers: false })
          Alert.alert('Error', `${res.error}! try again.`);
        }
      } catch (error) {
        console.log('error: ', error);
        this.setState({ isLoadingNumbers: false })
        Alert.alert('Error', 'request failed! try again.')
      }
    }
  }

  getContactName(number) {
    const { phoneContacts, countryCode } = this.state;
    if (phoneContacts.length) {
      let index = phoneContacts.findIndex(element => {
        let parsedNumber = element.phoneNumbers[0] ? element.phoneNumbers[0].number.replace(/[^a-zA-Z0-9]/g, '') : "";
        if (parsedNumber) {
          if (parsedNumber.slice(0, 1) === "0") {
            if (parsedNumber.slice(1, 2) === "0") {
              if (parsedNumber.substring(2) === number ||
                parsedNumber.substring(2).replace(`${countryCode}0`, countryCode) === number) {
                return number;
              }
            } else {
              return countryCode + parsedNumber.substring(1) === number;
            }
          } else {
            // console.log('nummm: ', parsedNumber, number);
            // return parsedNumber === number;
            if (parsedNumber === number ||
              parsedNumber.replace(`${countryCode}0`, countryCode) === number) {
              return number;
            }
          }
        }

      });
      if (Platform.OS === 'ios') {
        return index >= 0 ? phoneContacts[index].givenName : ''
      } else {
        return index >= 0 ? phoneContacts[index].displayName : ''
      }
    }
  }

В приведенном ниже коде я отображаю имя и номер телефона в списке.

            <View style={styles.container}>
              {this.state.contacts.length ?
                <FlatList
                  data={this.state.contacts}
                  extraData={this.state}
                  numColumns={1}
                  keyExtractor={(item, index) => index.toString()}
                  renderItem={({ item }) => (
                    <View style={styles.itemContainer}>
                      <View>
                        <Text style={{ color: '#000', fontSize: 20 }}>
                          {this.getContactName(item.phone_number)}</Text>
                        <Text style={{ color: '#000' }}>
                          {item.phone_number}</Text>
                      </View>
                      {item.selected ?
                        <TouchableOpacity onPress={() => this.removeContact(item)}>
                          <Icon name={"ios-add-circle"} size={26} color={primaryColor} />
                        </TouchableOpacity>
                        :
                        <TouchableOpacity onPress={() => this.selectContact(item)}>
                          <Icon name={"ios-add-circle"} size={26} color={'grey'} />
                        </TouchableOpacity>
                      }
                    </View>
                  )}
                />

Надеюсь, понятно, что я уже сделал. То, что мне сейчас нужно, я думаю, так или иначе. Это еще одна функция, которая объединяет имя и номер и сортирует их перед тем, как я их отрисовываю. По крайней мере, это то, что я думаю. Может быть, сортировка должна быть выполнена в рендере. Я не на 100% Я уже два дня пробую всевозможные способы и просто не могу заставить его отсортировать список контактов в алфавитном порядке. Любая помощь будет очень признательна.

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Вам нужно поместить имена в массив phoneNumbers, а затем отсортировать ... В настоящее время вы выбираете имя контакта при рендеринге телефонных номеров, поэтому нет никакой возможности предварительно отсортировать ...

    if (res.response) {
      console.log('contacssssst: ', res.contact_list);
      const contacts = res.contact_list.map((contact)=>{
//Loop through the contacts and add the display name found.
          contact.displayName = this.getContactName(contact.phone_number);
          return contact;
      });
//Sort using the displayName property.
      contacts.sort((a,b)=>{
           if(a.displayName > b.displayName){
               return 1;
           }
           if(a.displayName < b.displayName){
               return -1;
           }
           return 0;
      });
      this.setState({ contacts: res.contact_list, isLoadingNumbers: false })
    }

Тогда, по вашему мнению, вы можете получить прямой доступ к item.displayName.

Я написал функцию сортировки очень быстро, не слишком уверен, что она будет правильно сортироваться.

0 голосов
/ 11 марта 2020

@ salketer дал мне очень близкий к правильному ответу. Я закончил, используя другой способ сортировки. А также последний setState Мне нужно установить только контакты. Еще раз спасибо.

if (res.response) {
  console.log('contacts: ', res.contact_list);
    const contacts = res.contact_list.map((contact)=>{
        contact.displayName = this.getContactName(contact.phone_number);
        return contact;
    });
  contacts.sort((a, b) => a.displayName.localeCompare(b.displayName));
  console.log('contacts_returned: ', contacts);
  this.setState({ contacts, isLoadingNumbers: false })
}
...