【问题标题】:How to filter out a state array values based on elements located in another array in state?如何根据状态中位于另一个数组中的元素过滤出状态数组值?
【发布时间】:2020-08-17 11:56:25
【问题描述】:

我的状态数据如下所示:

 state = {
      search: “”
      tagValue: “”
      data: [
           {  
              id: 1,
              fName: "Henry",
              lName: "Jones"
              email: “lol@hotmail.com”,
              gpa: “3.6”
              tag: [
                   "hello", "bye"
              ] 
           },
           {  
              fName: "Jeffrey",
              lName: "Johnston”,
              email: “hehdbejeu@gmail.com”,
              gpa: “2.6”,
              tag: [
                   "hello", "bye"
              ] 
           },
           {  
              fName: "Henry",
              lName: "Jones"
              gpa: “1.9”
              tag: [
              ] 
           }
      ]
  }

我已经弄清楚了如何根据用户输入过滤数据数组:

 let studentListFilter = this.state.data.filter((student) => {
       return (
         student.firstName
           .toLowerCase()
           .indexOf(this.state.search.toLowerCase()) !== -1 ||
         student.lastName
           .toLowerCase()
           .indexOf(this.state.search.toLowerCase()) !== -1
 }

然后在我的渲染方法中返回 studentListFilter。 search 是根据用户输入更新的状态值。但是我无法弄清楚如何将位于数组中的值(在这种情况下特别是标记)与用户输入进行比较。

我试过这样做无济于事:

let studentListFilter = this.state.data.filter((student) => {
      return (
        student.fName
          .toLowerCase()
          .indexOf(this.state.search.toLowerCase()) !== -1 ||
        student.lName
          .toLowerCase()
          .indexOf(this.state.search.toLowerCase()) !== -1 ||
        student.tag.map(
          (individualTag) =>
            individualTag
              .toLowerCase()
              .indexOf(this.state.tagValue.toLowerCase()) !== -1
        )
      );
    });

任何帮助都会很棒

【问题讨论】:

  • 请在codesandbox.io 中提供工作示例,重现您的问题以便更好地理解..
  • 您只是想检查tagValue 是否包含在至少一个student.tag 数组中?
  • 我想看看它是否至少类似于 student.tag 数组中的元素之一
  • 你能用你过滤的数据和你过滤的对象更新你的问题吗?下面的答案是正确的,但我们需要查看过滤对象的结构。
  • 我已经更新了帖子中状态数据的结构。数据数组中的每个元素都应该提供有关研究的信息。我几乎通过 studentListFilter 映射数组中的数据对象,并显示 firstnamelastname、gpa、email 的各个 div。用户可以将字符串输入到每个学生的标签数组中。并且有两个文本输入,第一个允许按名字或姓氏过滤数据数组,第二个允许用户根据每个学生的标签进行过滤。

标签: reactjs filter state


【解决方案1】:

其中一个问题是,当检查任何字符串值是否包含过滤输入时,所有字符串都包含空字符串。

console.log("test".indexOf('') !== -1);
console.log("test".includes(''));

因此,当您有两个过滤输入并假设它们适用于数据时,就会出现问题。因为如果输入之一为空,则上述条件之一始终为真,因此永远不会过滤数据。

  1. 需要更改关于空过滤器字符串的假设,如果它们为空,则不应进行过滤,因此仅在过滤器字符串为真时应用搜索,即。非空字符串。
  2. 如果两个过滤器都处于活动状态,则首先进行条件测试,以打破平局
  3. 第二次单独测试每个条件
  4. 返回 true 以完全不过滤数据

过滤逻辑:

this.state.data
  .filter(student => {
    if (this.state.search && this.state.tagValue) {
      return (
        (student.fName.toLowerCase().includes(this.state.search) ||
          student.lName.toLowerCase().includes(this.state.search)) &&
        student.tag.some(tag => tag.toLowerCase().includes(this.state.tagValue))
      );
    }
    if (this.state.search) {
      return (
        student.fName.toLowerCase().includes(this.state.search) ||
        student.lName.toLowerCase().includes(this.state.search)
      );
    }
    if (this.state.tagValue) {
      return student.tag.some(tag =>
        tag.toLowerCase().includes(this.state.tagValue)
      );
    }
    return true;
  })

可以看出有很多重复,多一点 DRY 方法:

{this.state.data
  .filter(({ fName, lName, tag }) => {
    const includesName = [fName.toLowerCase(), lName.toLowerCase()].some(
      name => name.includes(this.state.search)
    );
    const includesTag = tag.some(tag =>
      tag.toLowerCase().includes(this.state.tagValue)
    );

    if (search && tagValue) {
      return includesName && includesTag;
    }
    if (search) {
      return includesName;
    }
    if (tagValue) {
      return includesTag;
    }
    return true;
  })

【讨论】:

    【解决方案2】:

    基本上您可以将some 用于您的用例:

    类似这样的:

        let studentListFilter = this.state.data.filter((student) => {
          const matchFirstName = student.fName
            .toLowerCase()
            .indexOf(this.state.search.toLowerCase()) !== -1;
    
          const matchLastName = student.lName
            .toLowerCase()
            .indexOf(this.state.search.toLowerCase()) !== -1
    
          // will return true if one of your tags match the search
          const someFnCB = (individualTag) => {
     return individualTag.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1 
    };
    
    
          const matchTag = student.tag.some(someFnCB)
    
    
          return matchFirstName || matchLastName || matchTag;
        });
    

    【讨论】:

    • 有什么方法可以查看 individualTag 是否至少相似,而不必与 tagValue 状态属性完全匹配?
    • 如果individualTag 中的任何一个与搜索字符串匹配,some 函数将返回 true。所以如果你寻找aw 并且你有标签awesome awful raw nothing 前三个标签将匹配
    • 我得到一个 individualTag.toLowerCase() 不是函数
    • 我已将 .toString() 添加到 individualTag,因此我不再收到错误消息,但状态仍无法过滤
    猜你喜欢
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多