【问题标题】:Returning a filtered nested array inside an array of objects in React在 React 的对象数组中返回过滤的嵌套数组
【发布时间】:2021-12-26 08:29:54
【问题描述】:

我有一条处于“serviceProviders”状态的数据,它保存数据如下:

[
  {
    "id": 1,
    "name": "Mental Wellness",
    "services": [
      {
        "name": "Footcare & more",
        "serviceType": "Footcare",
        "location": {
          "lat": 43.65040363335024,
          "lng": -79.38396226829892
        }
      },
      {
        "name": "Brain Wellnes",
        "serviceType": "Mental",
        "location": {
          "lat": 43.655931348619475,
          "lng": -79.37928150811159
        }
      },
      {
        "name": "Physical service",
        "serviceType": "Physical",
        "location": {
          "lat": 43.70312522921196,
          "lng": -79.34393786935266
        }
      }
    ]
  }
]

我想编写一个函数,该函数基于将 serviceType 与其他变量匹配来过滤嵌套数组(服务),并返回带有更新后的服务数组的整个对象并设置新状态。

类似的东西:

  const filter = () => {
    serviceProviders.map((provider) => {
      const filtered = provider.services.filter((service) => service.serviceType === 'Mental')
      setServiceProviders(serviceProviders => [...serviceProviders, serviceProviders.services = filtered ])
    })
  }

应该返回:

[
  {
    "id": 1,
    "name": "Mental Wellness",
    "services": [
      {
        "name": "Brain Wellnes",
        "serviceType": "Mental",
        "location": {
          "lat": 43.655931348619475,
          "lng": -79.37928150811159
       }
    ]
  }
]

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 不明白有什么不清楚的地方?用户将拥有一组 serviceTypePreferences,它们将针对 serviceTypes 进行测试并查找匹配项。无论如何,功能不会改变
  • 假设有多个顶级提供者,其中一些没有任何匹配的服务......结果中的那些顶级对象会发生什么
  • 总是可以检查的。如果我无法让查询工作,我什至无法做到这一点。这也是为什么我想要一个包含所有内容的状态,以及一个包含过滤结果(如果有)的状态。
  • 我只是在问会发生什么?实际上只有两个选择;完全过滤掉那些顶级对象或将它们包含在空的services数组中
  • 所以最好如果没有匹配项则返回原始服务数组

标签: arrays reactjs filter use-state


【解决方案1】:

首先,我建议使用 useMemo 挂钩来创建转换集,这样您就不会改变原始数据。

根据您的评论将服务过滤到具有选定serviceType 或的服务...

如果没有匹配则返回原始服务数组

试试这个...

const [ serviceProviders, setServiceProviders ] = useState([
  // your array data here
])
const [ serviceType, setServiceType ] = useState("Mental")

const providers = useMemo(() => {
  const predicate = svc => svc.serviceType === serviceType

  return serviceProviders.map(sp => ({
    ...sp,
    services: sp.services.some(predicate) // are there matches
      ? sp.services.filter(predicate) // yes, use the filtered array
      : [...sp.services] // no, clone the original array
  }))
}, [ serviceProviders, serviceType ]) // dependencies

只有当任何一个依赖发生变化时,这个记忆值才会重新计算。


如果你想完全过滤掉没有匹配的顶级对象,试试这个

return serviceProviders.filter(sp => sp.services.some(predicate))
  .map(sp => ({
    ...sp,
    services: sp.services.filter(predicate)
  }))

【讨论】:

  • 惊人的解决方案。与 useMemo 相比,您将如何将 return 设置为新的状态。假设 serviceType(s) 可以根据用户偏好动态变化,并且查询需要再次发生并且状态需要更新。我的语法与您的非常相似,但是当我尝试将其设置为一段新的代码状态时失败了。谢谢!
  • 如果它只是从现有状态派生的,你不应该需要它作为状态。这正是useMemo 的用途;任何时候你的状态发生变化,备忘录都会重新计算
  • 明白了!非常感谢!
猜你喜欢
  • 2017-03-08
  • 1970-01-01
  • 2021-05-02
  • 2018-01-27
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
相关资源
最近更新 更多