I have a piece of data in a 'serviceProviders' state which holds data as so:
[
{
"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
}
}
]
}
]
I want to write a function which filters the nested array(services) based on matching serviceType to some other variable and returns the whole object with the updated services array and sets a new state.
something along these lines:
const filter = () => {
serviceProviders.map((provider) => {
const filtered = provider.services.filter((service) => service.serviceType === 'Mental')
setServiceProviders(serviceProviders => [...serviceProviders, serviceProviders.services = filtered ])
})
}
should return:
[
{
"id": 1,
"name": "Mental Wellness",
"services": [
{
"name": "Brain Wellnes",
"serviceType": "Mental",
"location": {
"lat": 43.655931348619475,
"lng": -79.37928150811159
}
]
}
]
any help would be much appreciated. thank you.
CodePudding user response:
First, I'd suggest using the useMemo hook to create transformed sets so you don't mutate your original data.
To filter down the services to ones with the selected serviceType
or as per your comment...
if there are no matches then return the original services array
try this...
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
This memoized value will only recompute if either of the dependencies change.
If you wanted to completely filter out top-level objects with no matches, try this instead
return serviceProviders.filter(sp => sp.services.some(predicate))
.map(sp => ({
...sp,
services: sp.services.filter(predicate)
}))