-3

I have a list of objects and I have to search them by id and name. Some of my objects have 'name': null and I get an error

Cannot read property 'includes' of null

Object.keys(result).forEach(key => {
      if (this.filters.searchBy && this.filters.searchBy.length) {
        result[key] = result[key].filter(r =>
          this.filters.searchBy.includes(r.id) ||
          r.name.includes(this.filters.searchBy));
      }
    });

I have tried

if (r.name !== null) {

}

but it is not a correct syntax

user2004
  • 1,783
  • 4
  • 15
  • 42
  • 1
    have you tried comparing with "!=", not "!==" ? – Skywarth Apr 29 '20 at 13:14
  • @Skywarth null object can be checked against with strict comparaison, `null === null` returns `true`, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null – Saadi Toumi Fouad Apr 29 '20 at 13:20
  • You should realize, that for arrow functions, you can write `x => { }`, where { } is a BlockStatement. Please review the different [arrow function syntax options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). Also notice, that `function () { }` also works. This comment is in regards to your "not a correct syntax", and your comment of "can't have an if in a filter method". – ASDFGerte Apr 29 '20 at 13:20

4 Answers4

2

Optional Chaining & Arrow Functions

You can use ?. to avoid having to check nulls on properties. Also, you can use arrow functions to easily filter an array in JavaScript.

Here is some example code:

let list = [
  {name: 'John Smith', age: 13},
  {name: 'Peter Jones', age: 23},
  {name: 'Jane Doe', age: 54},
  {name: null, age : 12},
  {age: 72}
];

let result = list.filter(i => {
    return (
        i.name?.startsWith("J") &&
        i.age < 40
    )
});

console.log(result);
// Returns only "John Smith"

Without Optional Chaining

As Makyen pointed out, you may not be able to us optional chaining. In that case you can just check each field before using it, as shown below.

let list = [
  {name: 'John Smith', age: 13},
  {name: 'Peter Jones', age: 23},
  {name: 'Jane Doe', age: 54},
  {name: null, age : 12},
  {age: 72}
];



let result = list.filter(i => {
    return (
        i.name && // If 'name' is null the condition will fail fast
        i.name.startsWith("J") &&
        i.age < 40
    )
});

console.log(result);
// Returns only "John Smith"

I found a function on a different question (https://stackoverflow.com/a/23809123/8779719) which allows you to easily check nested objects. I've slightly modified it to check for nested fields.

function get(obj, key){
  return key.split(".").every(function(x) {
        if(typeof obj != "object" || obj === null || ! x in obj || !obj[x])
            return false;
        obj = obj[x];
        return true;
    });
}

let list = [
  {
    name: {
      firstName: 'John', lastName: 'Smith' 
    },
    age: 13
  },
  {
    name: {
      firstName: null, lastName: 'Jones' 
    },
    age: 23
  },
  {
    name: {
      lastName: 'Jones' 
    },
    age: 46
  }
];

let result = list.filter(i => {
    return (
        get(i, "name.firstName") && 
        i.name.firstName.startsWith("J") &&
        i.age < 40
    )
});

console.log(result);
// Returns only "John Smith"

Links:

Optional chaining

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Arrow functions - a good article I wrote about arrow functions

https://dev.to/acroynon/javascript-arrow-functions-explained-3m04

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
acroynon
  • 60
  • 1
  • 7
1

without the if, you simply write:

&& (r.name !== null)

in your expression and the compiler will accept it, or you can use the filter as follows:

.filter( (item) => {
  if (whatever_condition) {
    return item;
}
});
Giggs
  • 851
  • 10
  • 16
0

You can just do:

Object.keys(result).forEach(key => {
      if (this.filters.searchBy && this.filters.searchBy.length) {
        result[key] = result[key].filter(r => r && 
          (r.id && this.filters.searchBy.includes(r.id)) ||
          (r.name && r.name.includes(this.filters.searchBy)));
      }
    });
German Quinteros
  • 1,870
  • 9
  • 33
-1

Have u tried this

if (r.name) {}
Zumm
  • 876
  • 2
  • 8
  • 12