【问题标题】:Sorting Phone Contacts With React Native使用 React Native 对电话联系人进行排序
【发布时间】:2020-03-10 13:11:31
【问题描述】:

我的 react-native 应用程序向拥有我的应用程序的用户电话簿中的联系人发送类似于消息的内容。因此,当用户注册时,他们只注册使用我的应用程序,他们只注册他们的电话号码。在向联系人发送消息时。我访问他们的电话簿并将其与我在 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%。两天来我一直在尝试各种方法,但似乎无法让它按字母顺序对联系人列表进行排序。非常感谢任何和所有帮助。

【问题讨论】:

    标签: javascript react-native sorting react-native-flatlist


    【解决方案1】:

    需要将姓名放入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。

    我写的排序函数很快,不太确定是否能正确排序。

    【讨论】:

    • 它仍然给我同样的结果。我仍然得到名字,但他们没有排序。我非常感谢您的帮助。你觉得我可能做错了什么吗? item.displayName 正在提取名称。只是没有排序。
    • 只是一个更新。如果我 console.log(contacts) 就在底部的那个 set.State 之上。它实际上是按字母顺序返回名称。所以我需要访问一些不同的东西才能看到它们。 item.displayName 或 item.contacts.displayName 或 item.contacts 不起作用。第一个只显示未排序的列表。另外两个是空白的。我不知道如何显示得到返回的正确排序列表
    【解决方案2】:

    @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 })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多