【问题标题】:How to filter nested objects? ReactJS如何过滤嵌套对象?反应JS
【发布时间】:2017-11-21 08:56:27
【问题描述】:

数据样本:

nodes:[
        {
        label:"Egor1",
        value:"Egor1",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"2",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"3 days ago",
          vmcount:"",
          restorePointsCount:"11",
        },
        {label:"disk22222222222222",
        value:"disk2",
        name:"jobname2",
        restorePoint:"4 days ago",
        vmcount:"",
        restorePointsCount:"11"},
        {label:"disk555",
        value:"disk552",
        name:"jobnam555e2",
        restorePoint:"4 days ago",
        vmcount:"",
        restorePointsCount:"11"}
      ]}
      ,

      {
        label:"Egor12",
        value:"Egor12",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"22",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"2 days ago",
          vmcount:"",
          restorePointsCount:"12",
        },
        {label:"disk22222222222222",
        value:"disk2",
        name:"jobname2",
        restorePoint:"restorepoint4",
        vmcount:"",
        restorePointsCount:"12",}
      ]},


      ],

尝试下一步:

filter(e) {
    var value = e.target.value;
    this.setState({filterval: value})
    this.setState({
      filteredItems: !value
        ? false
        : this.state.nodes.filter(function (item) {
          return 
          item.children.value.toLowerCase().indexOf(value.toLowerCase()) !== -1;
        })
    })
  }

但是过滤器想要工作,如何通过嵌套对象过滤?找不到任何示例。可以用 _lodash 做吗?

例如我搜索 标签:“磁盘111111111111111

结果必须是这样的数组:

{
        label:"Egor1",
        value:"Egor1",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"2",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"3 days ago",
          vmcount:"",
          restorePointsCount:"11",
        },

所以它不仅必须返回我搜索的元素,还必须返回有父母的孩子。

【问题讨论】:

  • 为什么要连续打两次this.setState
  • 因为第一个进入输入,第二个进入过滤数组
  • 你要过滤什么
  • 所有孩子,可以有很多孩子

标签: javascript reactjs filter


【解决方案1】:

您可以混合使用mapfilter。第一个映射每个项目并过滤其子项(根据您的需要),第二个过滤具有 children.length > 0

的项目

const nodes = [
  {
    label: 'Egor1',
    value: 'Egor1',
    restorePoint: '25/10/2017 10:00:29 PM',
    vmcount: '2',
    restorePointsCount: '',
    children: [
      {
        label: 'disk111111111111111',
        value: 'disk1',
        restorePoint: '3 days ago',
        vmcount: '',
        restorePointsCount: '11',
      },
      {
        label: 'disk22222222222222',
        value: 'disk2',
        name: 'jobname2',
        restorePoint: '4 days ago',
        vmcount: '',
        restorePointsCount: '11',
      },
      {
        label: 'disk555',
        value: 'disk552',
        name: 'jobnam555e2',
        restorePoint: '4 days ago',
        vmcount: '',
        restorePointsCount: '11',
      },
    ],
  },
  {
    label: 'Egor12',
    value: 'Egor12',
    restorePoint: '25/10/2017 10:00:29 PM',
    vmcount: '22',
    restorePointsCount: '',
    children: [
      {
        label: 'disk111111111111111',
        value: 'disk1',
        restorePoint: '2 days ago',
        vmcount: '',
        restorePointsCount: '12',
      },
      {
        label: 'disk22222222222222',
        value: 'disk2',
        name: 'jobname2',
        restorePoint: 'restorepoint4',
        vmcount: '',
        restorePointsCount: '12',
      },
    ],
  },
]

const value = 'disk552'

const result = nodes
  .map(item => ({
    ...item,
    children: item.children
      .filter(child => child.value.includes(value.toLowerCase()))
  }))
  .filter(item => item.children.length > 0)
  
console.log(result)

【讨论】:

  • 它只过滤父母正确的,例如我搜索值为disk552的孩子,它返回包含在这个父母中的3个元素
  • @egorchik 我刚刚更新了我的答案。请再次检查:)
【解决方案2】:

您的item.children 是一个数组。如果里面只有一项,那么你可以item.children[0]。否则,你也必须循环它来检查你的情况。

【讨论】:

  • 那么就像我说的,你也必须遍历它们。
  • 请将完整的输入 JSON 添加到问题并输出您所期望的。
  • 添加,请看
【解决方案3】:

您可以在nodes 上使用filter,然后测试children.value 以查看要保留哪些节点。

const FakeReact = {
  setState(newState) {
    this.state = Object.assign({}, this.state, newState)
  },
  state: {
    nodes: [
      { value: "Egor1", children: [{ value: "disk1" }, { value: "disk2" }] },
      { value: "Egor2", children: [{ value: "disk3" }, { value: "disk4" }] },
    ]
  }
}

const fakeEvent = { target: { value: 'disk1' }}

function filter(e) {
  const value = e.target.value;
  const regex = new RegExp('.*' + value + '.*', 'gi')
  this.setState({
    filterval: value, // may as well only make one call to set state
    filteredItems: (!value)
      ? [] // try to keep the same type for the false value
      : this.state.nodes.filter(
        // filter the node
        node =>
          node.children.find(
            // check if the child value matches the input value
            // if it does the node will be returned to filteredItems
            child => regex.test(child.value)
          )
        )
  })
}

// call filter with the FakeReact as the context and a fake event
filter.call(FakeReact, fakeEvent)

console.log('nodes', FakeReact.state.nodes)
console.log('filteredItems', FakeReact.state.filteredItems)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js?theme=onedark"></script>

【讨论】:

    猜你喜欢
    • 2021-10-29
    • 1970-01-01
    • 2019-02-11
    • 2020-07-28
    • 1970-01-01
    • 2020-02-01
    相关资源
    最近更新 更多