Justin Handley Justin Handley - 9 days ago 9
React JSX Question

I need to do a lodash filter based on the key of a child element

I am trying to use lodash to filter objects in a react app.

const filteredContacts = _(contacts)
.map((contact, id) => ({_id: id, ...contact}))
.filter(contact => !(this.state.filter && contact.lastName.toLowerCase().indexOf(this.state.filter) == -1 && contact.firstName.toLowerCase().indexOf(this.state.filter) == -1))
.filter(c => {
_(c.courses)
.map((course, id) => ({_id: id, ...course}))
.each(course => {
console.log(course._id)
return (course._id == this.state.courseId)
})
})


This is pulling from a firebase database, so there are nodes which are just a key, no value, that then have children. In this case I have capitalized where those are below.

contacts > USERID > courses > COURSEID > coursedata

or

contacts: {
-uf39uhef2: {
name: blah,
courses: {
-dfh92ehfdsfhw: {
coursename: name
}
}
}
}


I know that my second filter is all kinds of wrong - I just pasted the last iteration of a million tries. this.state.courseId is the course ID I want to filter by - how can I accomplish this?

I want to return all users that have a course ID matching the one set in state.

Answer

In the filter check if the contact has courses, and if coureses[this.state.courseId] is truthy:

const filteredContacts = _(contacts)
        .map((contact, id) => ({_id: id, ...contact}))
        .filter(({ courses }) => _.has(courses, this.state.courseId));

const contacts = {
  '-uf39uhef2': {
    name: 'blah',
    courses: {
      '-dfh92ehfdsfhw': {
        coursename: 'name'
      }
    }
  },
  '-willBeFiltered': {
    name: 'willBeFiltered',
    courses: {
      '-willBeFiltered': {
        coursename: 'name'
      }
    }
  }
};

const courseId = '-dfh92ehfdsfhw'; // courseId = this.state.courseId

const filteredContacts = _(contacts)
        .map((contact, id) => ({_id: id, ...contact}))
        .filter(({ courses }) => _.has(courses, courseId));

console.log(filteredContacts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

You can also do this without lodash:

const filteredContacts = Object.keys(contacts)
    .map((id) => ({_id: id, ...contacts[id]}))
    .filter(({ courses }) => courses && courses[this.state.courseId]);
Comments